Sometimes text fields should be exact-match
Search on analyzed text fields will return anything remotely relevant
ElasticSearch를 이용하면서 텍스트 필드와 검색어가 정확히 일치하며 대소문자 까지 일치하는 데이터를 검색하기 위해서는 keyword 매핑을 적용해야하며,
이 외에는 분석기(analyzer)를 사용하여 대소문자를 구분하지 않으며 동의어 까지 찾아 내는 검색을 수행할 수 있다.
다음과 같은 명령어를 실행해보자
curl -XGET 127.0.0.1:9200/movies/_search?pretty -d '
{
"query": {
"match": {
"title": "Star Trek"
}
}
}'
그러면 우리는 "Star Trek"에 대한 질문의 결과로 "Star Trek"과 "Star Wars"라는 영화들을 결과로 받게 될 것이다. (부분 매치)
장르를 검색하면 어떻게 될까? 다음과 같은 명령어를 수행해보자 (구절 매치 사용)
curl -XGET 127.0.0.1:9200/movies/_search?pretty -d '
{
"query": {
"match_phrase": {
"genre": "sci"
}
}
}'
소문자 'sci'를 검색했음에도 모든 "Sci-Fi" 영화가 결과로 나올 것이다.
왜냐하면 genre 필드가 분석(analyzing)되기 때문이다. 무슨 말이냐면, 분석기가 장르 필드의 "Sci-Fi"에서 "-"를 보고 독립적인 두개의 용어가 있음을 인지할 것이다. 그리고 데이터를 정규화하기 위해 모든 것을 소문자로 변환하고 융통성 있게 검색을 수행하는 것이다.
만약 검색의 융통성을 원하지 않는다면 keyword 매핑을 적용해야한다.
대부분, 매핑은 한 번 적용되면 변경할 수 없다. 따라서 전체 색인을 먼저 삭제하고 새로 매핑을 수행한뒤 새로운 색인을 만들겠다.
curl -XDELETE 127.0.0.1:9200/movies
curl -XPUT 127.0.0.1:9200/movies -d '
{
"mappings": {
"properties": {
"id": { "type": "integer" },
"year": { "type": "date" },
"genre": { "type": "keyword"},
"title": { "type": "text", "analyzer": "english"}
}
}
}'
위와 같은 매핑을 통해 genre 필드를 검색할때는 정확히 일치하는 데이터만 가져올 수 있다. title 필드는 text이므로 자동으로 분석기가 적용된다. 분석기는 개발자가 임의로 정할 수 도 있다. title 필드에 적용된 분석기는 english 분석기로 영어의 고유한 stop word와 동의어등을 적용할 수 있다.
이제 벌크 작업을 통해 movies라는 이름을 갖는 색인을 다시 만들어보자
curl -XPUT 127.0.0.1:9200/_bulk?pretty --data-binary @movies.json
이제 다시 "sci"라는 genre를 검색해보자
curl -XGET 127.0.0.1:9200/movies/_search?pretty -d '
{
"query": {
"match": {
"genre": "sci"
}
}
}'
결과로 아무것도 검색이 되지 않는 것을 확인할 수 있다. 대소문자를 포함한 정확한 매치만 허용하기 때문이다.