복합명사로 검색할 때와 명사를 띄어 써서 검색할 때 검색 결과가 다르게 나타납니다.
그 이유를 설명드리겠습니다.
name 이란 필드에서 "만성간염" 이란 단어를 검색한다고 가정하겠습니다.
현재는 "만성간염"을 KoreanFilter 로 처리하면,
| term position | 1 |
|---|
| term text | 간염 |
|---|
| 만성간염 |
| 만성 |
처럼 나옵니다. term position 이 동일한 것들은 유의어 처럼 처리를 합니다.
name:간염 name:만성간염 name:만성
이 됩니다. 따라서, "간염", "만성간염", "만성" 이 세 개의 단어 중 하나라도 들어있는 문서가 검색이 됩니다.
즉, OR 검색이 되는 것이죠. 이것은 solr 에서
<solrQueryParser defaultOperator="AND"/>
와 같이 설정을 하였더라도 유의어로 보기 때문에 위와 같이 Query 가 생성이 됩니다.
그 다음 "만성 간염"으로 띄워서 쓰면 어떻게 될까요? solr analysis 에서 보면 아래와 같습니다.
| term position | 1 | 2 |
|---|
| term text | 만성 | 간염
|
|---|
Query 를 생성할 때는 "만성", "간염"을 먼저 분리한 후, name 필드를 각각 적용하게 됩니다.
그래서 defaultOperator 가 AND 일 때
+name:만성 +name:간염
으로 Query 가 생성됩니다. "만성"과 "간염"이 동시에 들어있는 문서가 검색 결과로 나옵니다.
defaultOperator 가 OR 이면,
name:만성 name:간염
으로 Query 가 생성이 되고, "만성" 또는 "간염" 이 들어있는 문서가 검색됩니다.
만약에 KoreanFilter 를 수정해서 term position 을 달리하면 어떻게 될까요? 실제로 KoreanFilter 를 수정을 해서 실험을 해보았습니다.
| term position | 1 | 2 |
|---|
| term text | 만성 | 간염 만성간염 |
|---|
하나의 token 이 term position 이 다른 여러 개의 token 들로 쪼개질 때는
즉, 최종 Query 의 스트링은
name:"만성 (간염 만성간염)"
으로 생성이 됩니다. 엉뚱하게도 "만성 (간염 만성간염)"으로 exact 매칭을 시도하기 때문에,
이런 경우엔 "만성간염"이 당연히 결과에 나오지 않습니다.
만약, "만성간염"을
| term position | 1 | 2 |
|---|
| term text | 만성 | 간염 |
|---|
name:"만성 간염"
으로 검색을 하기 때문에 "만성 간염"으로 exact 매칭을 하여 "만성간염"은 검색되지 않습니다.
조금 내용이 헛갈리실 수도 있는데, 결론적으로 말씀드리면, lucene 의 기본
QueryParser 클래스를 이용해서는 복합명사에 대해 AND 검색이 안 된다는 점입니다.
"만성간염"을 입력했을 때, "만성간염", "만성 간염" 뿐만 아니라, "B형간염", "A형간염", "간염" 등의 결과가 같이 나올 수 밖에 없습니다.
KoreanFilter 를 사용하지 않았을 때는 반대로 "만성간염"을 입력해서 "만성 간염"을 찾을 수 없게 됩니다.
아무래도 복합명사 AND 검색이 가능하게 하려면, query parser 를 별도로 하나 만들어야 할 거 같습니다.