최근 우리 서비스에서 "아쉬아간다"
같은 영양제명을 검색할 때, 원하는 제품 대신 관련 없는 제품이 노출되는 문제가 있었습니다.
예시:
"아쉬아간다"
"히든 핏 가르시니아 포 우먼"
그리고 "힌트"
가 포함된 제품이 2개 있었는데 1개만 나오는 문제가 있었습니다.
"힌트 리스펙타 질 유산균"
원인을 분석한 결과:
"아쉬아간다"
→ "아쉬"
, "쉬아"
, "아간"
등으로 분해되어 관련 없는 제품까지 검색 결과에 포함됨[^\uAC00-\uD7A3a-zA-Z0-9]
→ 공백까지 제거"힌트 리스펙타 질 유산균"
→ "힌트리스펙타질유산균"
"힌트"
검색 시 매칭 실패"혼합비타민C"
→ ["혼합", "비타민", "C"]
char_filter:
remove_extra_whitespace:
type: pattern_replace
pattern: "\\s+"
replacement: " "
remove_noise_chars:
type: pattern_replace
pattern: "[!@#$%^&*()=~`{}\\[\\]|\\\\:;\"'<>,?/]"
replacement: ""
"힌트 리스펙타 질 유산균"
→ ["힌트", "리스펙타", "질", "유산균"]
"힌트"
검색 시 정확히 매칭 가능Query matchPhraseQuery = Query.of(q ->
q.matchPhrase(mp ->
mp.field(searchType.getKey())
.query(FieldValue.of(keyword))
)
);
GET http://localhost:29200/supplement/_termvectors/264?fields=supplement_name&term_statistics=true
"힌트 리스펙타 질 유산균"
의 id=264_id = 264
)의 필드가 어떻게 이미 색인돼 있는지를 확인하는 용도term_vectors: {}
)"힌트리스펙타질유산균"
에 대한 색인 결과
{
...
"term_vectors":{
"supplement_name":{
"field_statistics":{
"sum_doc_freq":54439,
"doc_count":9177,
"sum_ttf":55237
},
"terms":{
"ᆯ":{
"doc_freq":185,
"ttf":186,
"term_freq":1,
"tokens":[
{
"position":6,
"start_offset":8,
"end_offset":10
}
]
},
"균":{
"doc_freq":405,
"ttf":405,
"term_freq":1,
"tokens":[
{
"position":8,
"start_offset":12,
"end_offset":13
}
]
},
"어":{
"doc_freq":283,
"ttf":292,
"term_freq":1,
"tokens":[
{
"position":4,
"start_offset":8,
"end_offset":10
}
]
},
"유산":{
"doc_freq":404,
"ttf":404,
"term_freq":1,
"tokens":[
{
"position":7,
"start_offset":10,
"end_offset":12
}
]
},
"유산균":{
"doc_freq":403,
"ttf":403,
"term_freq":1,
"tokens":[
{
"position":7,
"start_offset":10,
"end_offset":13
}
]
},
"지":{
"doc_freq":274,
"ttf":285,
"term_freq":1,
"tokens":[
{
"position":5,
"start_offset":8,
"end_offset":10
}
]
},
"질":{
"doc_freq":18,
"ttf":18,
"term_freq":1,
"tokens":[
{
"position":4,
"start_offset":8,
"end_offset":10
}
]
},
"타":{
"doc_freq":42,
"ttf":44,
"term_freq":1,
"tokens":[
{
"position":3,
"start_offset":6,
"end_offset":8
}
]
},
"트리스":{
"doc_freq":1,
"ttf":1,
"term_freq":1,
"tokens":[
{
"position":1,
"start_offset":1,
"end_offset":5
}
]
},
"펙":{
"doc_freq":8,
"ttf":8,
"term_freq":1,
"tokens":[
{
"position":2,
"start_offset":5,
"end_offset":6
}
]
},
"힌":{
"doc_freq":1,
"ttf":1,
"term_freq":1,
"tokens":[
{
"position":0,
"start_offset":0,
"end_offset":1
}
]
}
}
}
}
}
"힌트 리스펙타 질 유산균"
에 대한 색인 결과
{
...
"term_vectors":{
"supplement_name":{
"field_statistics":{
"sum_doc_freq":55092,
"doc_count":9177,
"sum_ttf":56014
},
"terms":{
"ㄹ":{
"doc_freq":236,
"ttf":240,
"term_freq":1,
"tokens":[
{
"position":6,
"start_offset":8,
"end_offset":9
}
]
},
"균":{
"doc_freq":408,
"ttf":408,
"term_freq":1,
"tokens":[
{
"position":8,
"start_offset":12,
"end_offset":13
}
]
},
"다":{
"doc_freq":46,
"ttf":46,
"term_freq":1,
"tokens":[
{
"position":4,
"start_offset":6,
"end_offset":7
}
]
},
"리스":{
"doc_freq":8,
"ttf":8,
"term_freq":1,
"tokens":[
{
"position":1,
"start_offset":3,
"end_offset":5
}
]
},
"유산":{
"doc_freq":406,
"ttf":406,
"term_freq":1,
"tokens":[
{
"position":7,
"start_offset":10,
"end_offset":12
}
]
},
"유산균":{
"doc_freq":406,
"ttf":406,
"term_freq":1,
"tokens":[
{
"position":7,
"start_offset":10,
"end_offset":13
}
]
},
"지":{
"doc_freq":223,
"ttf":228,
"term_freq":1,
"tokens":[
{
"position":5,
"start_offset":8,
"end_offset":9
}
]
},
"질":{
"doc_freq":18,
"ttf":18,
"term_freq":1,
"tokens":[
{
"position":5,
"start_offset":8,
"end_offset":9
}
]
},
"타":{
"doc_freq":39,
"ttf":41,
"term_freq":1,
"tokens":[
{
"position":3,
"start_offset":6,
"end_offset":7
}
]
},
"펙":{
"doc_freq":8,
"ttf":8,
"term_freq":1,
"tokens":[
{
"position":2,
"start_offset":5,
"end_offset":6
}
]
},
"하":{
"doc_freq":452,
"ttf":455,
"term_freq":1,
"tokens":[
{
"position":3,
"start_offset":6,
"end_offset":7
}
]
},
"힌트":{ // <- "힌트" 추가됨
"doc_freq":2,
"ttf":2,
"term_freq":1,
"tokens":[
{
"position":0,
"start_offset":0,
"end_offset":2
}
]
}
}
}
}
}
"아쉬아간다"
검색 시 정확히 포함된 제품만 반환"힌트"
검색 시 "힌트 리스펙타 질 유산균"
정상 노출