현재는 다니고 있는 회사에서는 태그를 기준으로 매칭하여 상품 검색을 진행하고 있다. (개편 진행 중)
지금 구현해 놓은 검색이 마음대로 되지 않는(?) 현상이 발생하였다.
여러 필드를 기준으로 검색을 하였지만, 그 중 한가지 필드에 대한 검색이 문제가 있어 원하는 데이터가 검색되지 않았던 것이다.
해당 필드는 text 타입으로 설정되어있었다. 현재는 다니고 있는 회사에서는 태그를 기준으로 매칭하여 상품 검색을 진행하고 있다.
지금 구현해 놓은 검색이 마음대로 되지 않는(?) 현상이 발생하였다.
여러 필드를 기준으로 검색을 하였을 때 그 중 한 가지 필드에 대한 검색이 문제가 있어 원하는 데이터가 검색되지 않았던 것이다.
예를 들어 "vehicle"라는 filed에 "electric bus"를 검색하였는데 해당 필드는 text 타입으로 설정되어있어 electirc과 bus로 나뉘어 검색이 되고 있었던 것이다. (원하던 상황은 "electric bus"를 통째로 검색하고 싶었다.)
💡 ElasticSearch string type 중 text와 keyword의 차이란?
- text 타입일 경우에는 형태소 기반으로 분리하기 때문에 단어 형태로 검색할 경우 전문 검색이 가능하다. (띄어쓰기 기준으로 tokenizer 진행)
- keyword 타입일 경우에는 exact value 즉, 완전 동일한 데이터에 대해 검색시 사용할 수 있다. (띄어쓰기까지 정확히 일치해야 한다.)
검색을 하던 도중 raw 라는 필드를 알게되었다.
filed 에 .raw가 붙는지 안 붙는지에 따라 결과가 달랐는데 이는 멀티 필드라는 개념때문이었다.
멀티 필드는 언제 사용하는가?
- 특정 필드에 풀 텍스트 검색 & 정렬 등을 동시에 사용하고 싶을 때
- 특정 필드에 여러 가지 분석기(Analyzer)를 적용하고 싶을 때
멀티 필드는 엘라스틱 서치 안에서 동일한 필드를 다른 용도로 사용하고자 할 때 무척 유용하다.
예를 들어 '상품 이름' 이라는 항목에 analyzer도 사용하고 싶고,
동시에 클러스터링이나 정렬도 사용하고 싶다면 난감할 수 있다.
keyword 필드 데이터에는 analyzer를 사용할 수 없고
text 필드 데이터는 정렬기능이 지원되지 않기 때문이다.
두 가지 특성을 모두 사용하고 싶을 때 fileds 파라미터를 추가하여 멀티 매핑을 하면 된다.
멀티 필드 설정
PUT my_index
{
"mappings": {
"properties": {
"vehicle": {
"type": "text",
"analyzer": "english"
"fields": {
"raw": {
"type": "keyword"
"normalizer": "custom_normalizer"
}
}
}
}
}
}
vehicle라는 이름의 데이터 타입을 정의하였다.
기본 타입은 text 타입에, english 분석기를 사용하도록 했다.
그리고 fields 파라미터로 "raw" 라는 자식을 따로 정의하였다.
자식 필드는 keyword 타입에, custom_normalizer 라는 노멀라이저를 사용한다.
(*분석기가 텍스트 타입에만 사용가능한 반면, 노멀라이저는 키워드 타입에 사용할 수 있고, 성능은 거의 동일한데 노멀라이즈는 단일화 토큰을 생성한다.)
필드 맵핑 확인
GET my_index/_mapping/field/vehicle
"mapping": {
"vehicle": {
"type": "text",
"fields": {
"raw": {
"type": "keyword",
}
}
}
}
해당 필드에 대한 정보를 확인할 수 있다.
위와 같은 문제는 해당 필드를 keyword를 기준으로 검색하면 해결되는 문제였어서 "vehicle.raw"를 사용하여 "electric bus"를 검색하니 해결이 되었다.
References
https://blog.voidmainvoid.net/314
https://stackoverflow.com/questions/38533249/elasticsearch-put-a-raw-field-inside-a-field