상품 검색의 자동완성과 동의어 사전을 만들려고 초기에는 search_logs 의 검색어를 가공 없이 그대로 Elasticsearch 키워드 색인에 올렸다. 항목이 3천 개를 넘긴 시점에 훑어보니 쓸모없는 것이 상당수 섞여 있었다.
Table of contents
Open Table of contents
상황 — 다섯 종류의 노이즈
GROUP BY keyword 로 나눠 패턴을 분류해 보니 노이즈가 다섯 종류로 갈렸다. 붙여 넣은 상품 URL 조각이 통째로 하나의 키워드가 돼 있었고 SKU-2024- 로 시작하는 상품 코드까지 항목으로 뽑혀 있었다.
관리자가 시험 삼아 친 test 와 asdf 도 있었는데 그것은 상품이 아니라 조작 흔적에 해당한다. 추상어와 명령 문자열이 섞여 있었고 대소문자만 다른 중복과 아무 상품에나 붙는 상품 같은 광범위 항목도 함께 있었다.
원인 — 왜 생기는가
원인을 따라가면 하나로 모이는데 추출이 검색어에서 토큰처럼 보이는 문자열을 전부 뽑기 때문이다.
URL 조각도 대문자로 된 상품 코드도 standard 토크나이저 입장에서는 단어처럼 보인다. 특히 관리자 화면의 검색이 문제였는데 운영자가 코드와 주소를 그대로 붙여 넣으므로 거기 있는 온갖 문자열이 후보가 된다.
해결 — 제외를 명시하고 앞에서 빼기
두 가지 방법이 있었는데 색인이 만들어진 뒤 노이즈를 주기적으로 지우는 것과 넣기 전에 stop 토큰 필터와 char_filter 로 거르는 것이다. 뒤쪽을 골랐다. 이유는 Elasticsearch 공식 문서대로 stop 필터는 토큰 스트림에서 목록의 단어를 제거하므로 색인 시점에 한 번 막히면 그 뒤로는 안 쌓여서다. 대신 stopwords_path 목록을 사람이 관리해야 하는 것을 감수했다. URL 패턴과 상품 코드 패턴과 test 같은 시험어와 광범위 단어를 그 목록에 넣었다.
뽑으라는 설정만 있고 빼라는 설정이 없으면 다 뽑는다. 더 앞에서도 막았는데 search_logs 를 넣을 때 관리자 화면 검색 자체를 제외했다. 고객이 무엇을 찾았는지는 의미가 있지만 운영자의 조회는 대부분 노이즈이고 입력에서 빼는 것이 필터로 거르는 것보다 확실하다.
판단 기준 — 초기에 지우는 값
삭제 대상을 세니 수십 개였고 URL 과 상품 코드와 시험어와 추상어와 중복과 광범위 단어로 나뉘었다. 이 시점에 지우는 것이 나중에 지우는 것보다 훨씬 싸다.
노이즈 항목이 동의어 병합 후보에 그대로 들어가기 때문이다. 새 검색어가 들어올 때마다 기존 것과 같은 뜻인지를 비교하는데 후보가 많을수록 비용이 늘고 비교에는 한계가 있다. 초기에 쳐 내면 그 뒤로 계속 이득이다.
주의 — 광범위 항목과 정규화
다섯 종류 중에서도 상품 같은 일반 명사 하나가 특히 나빴다. 아무 검색어나 그 항목에 붙으므로 연결이 계속 많아지고 자동완성에서 항상 나오는데 정작 아무것도 알려 주지 않는다.
너무 일반적인 항목은 관계를 흐리므로 없는 편이 낫다. 대소문자만 다른 중복은 lowercase 필터로 넣을 때 정규화해서 막았고 사후에 병합하는 것보다 그쪽이 맞다. 막는 지점은 입력과 추출과 정규화와 사후 삭제 순으로 앞쪽일수록 싼데 마지막만 하면 계속 쌓이는 것을 계속 지워야 한다.
정리
- 검색 로그를 그대로 넣으면 URL 조각과 상품 코드와 시험어가 항목이 된다
- 특히 관리자 화면 검색이 들어가면 온갖 문자열이 후보가 된다
- 뽑으라는 설정만 있고 빼라는 설정이 없으면 다 뽑는다
- 입력에서 빼는 것이
stop필터로 거르는 것보다 확실하다 - 노이즈는 동의어 병합 후보를 키운다
- 너무 일반적인 항목은 관계를 흐린다
- 대소문자 중복은
lowercase필터로 넣을 때 정규화한다 - 막는 지점이 앞일수록 싸다