Henry가 말했던 보완점에 대해서 보수를 하는 과정
score에 따른 정렬
상대적으로 관련성 있는 데이터 들이 상단에 위치하였다.
일부 개선된 부분은 있지만 정확하게 일치하는 값이 하단에 위치하는 경우가 발생하는데 이는, pik 제목의 경우 상대적으로 길이가 짧아 검색어와 정확히 일치하는 데이터가 나오기도 한다.
하지만 상대적으로 길이가 짧다보니 link 및 user와 비교해 볼때, score가 작게 측정되는 결과가 발생한다. 아래의 사진과 같이 중복 또한 제거하지 않았으며 상대적으로 적은 점수를 기록하고 있는 모습이다.
서로 다른 인덱스를 하나로 합치는 과정에서 발생하는 문제, 중복 또한 없애야 한다.
비공개 픽 자동완성에서 제거하기
테스트를 하면서 검색을 하는 과정에서 검색어로 제대로 넘어가지 않는 문제가 있었다. 예상하기로는 현재의 자동완성은 비공개 픽까지 포함을 하는데 이 과정에서 검색 권한이 없는 단어로 검색을 요구하여 실제로는 자동완성으로 제공하지만 검색 결과는 없는 일이 일어날 수 있다고 판단하였다.
권한을 필터링하는 코드를 추가하였다.
중복 제거
가장 효과적으로 중복을 제거하는 방법으로는 hash를 이용한 방법으로 대표적으로 set을 들 수 있을 것이다. → Serializer의 내장 함수 및 타입을 건드려야 하기 때문에 그리 좋은 시도는 아닌것 같다.OrderedDict
에 대한 __hash__
를 수정하여 set을 이용한 빠른 중복제거를 생각해보자!
ES에서 쿼리로 distinct 옵션이 존재하는지 확인해 보도록 하자 → aggregation을 활용하자
pik_qs = PikLightDocument.search()
pik_qs = pik_qs.query(
Q('prefix', title__raw={'value': q}) |
Q('fuzzy', title={'value': q, 'fuzziness': 1}) |
Q('match', title=q)
)
a = A('terms', field='title.raw')
pik_qs.aggs.bucket('count', a)
results = pik_qs.execute()
집계결과는 위와 같다.
aggregation을 이용할 경우 중복 제거와 문서의 숫자를 통계결과로 알 수 있다. 하지만 기존의 _score
를 불러와서 순서대로 적용하는 방식이 까다롭다고 느꼈고 파이썬 코드로 이를 정렬하는 방식을 택했다.
간단하게 .highlight(<field_name>)
을 통해서 다음과 같이 dsl 쿼리에 하이라이트 옵션을 추가하는 것은 간단하다.
쿼리
하지만 위의 결과는 인덱싱을 어떤 방식으로 했느냐가 중요한 부분을 차지하였다.
하이라이팅 결과
키워드로 분석한 title.raw
의 경우는 하나의 뭉치가 강조되어서 나왔고, 반면에 기본으로 분석한 title
의 경우는 띄어쓰기를 기준으로 나타나게 되었다.
해결방법
해결방법에는 여러가지가 있을 것으로 판단된다. 먼저 인덱싱을 하는 기준을 바꾸는 것이다. 기본적으로 인덱싱이 모두 키워드 혹은 음절 단위로 이루어졌기 대문에 정확한 하이라이팅이 불가능 하다.
네이버의 자동완성을 살펴보면 ngram 단위로 이루어지는 것을 볼 수 있다. 이러한 방식을 구현하기 위해서는 ngram 혹은 edge_ngram을 이용해야 하지만 이러한 방식을 인덱싱의 용량을 증가시키는 원인이 된다.
→ 기존의 “나의 컨텐츠 찾기”에서는 이러한 문제를 해결하기 위해서 serialiser를 이용한 커스텀 하이라이팅을 구현하였다. 하지만 자동완성의 경우는 이러한 과정에서 소비하는 시간이 검색경험을 해칠 수 있다는 판단을 하였다.
일단 유저의 이름은 ngram을 저장을 하고 있기 때문에 유저에 대해서는 ngram에 해당하는 하이라이팅 기능을 만들어 보자
token_filter가 아닌 tokenizer를 이용하면 해결이 가능하다고 한다. 애널라이저를 바꾸고 인덱싱을 다시 하였다.