ES Custom analyzer, Common Gram

parkhyoungjunparkhyoungjun
2 min read

Problem

분석기 이슈

  • 특수문자를 분리 하려다가 실수형에 '.'이 붙어있으면 분리되는 이슈가 발생했다
ex) 3.5kg => 3, ., 5, kg
  • 숫자 '3', '5'가 각각 토큰으로 분리되어 색인되는게 문제!

  • 만일 '5kg'이라고 검색 시 리턴이 돼버린다

ex) 검색어 '현미쌀 5kg'
문서1: 맛좋고 싱싱한 국내산 현미쌀 5kg
문서2: 값싸고 가성비 좋은 현미쌀 2.5kg

'5kg'에 문서 1만 match가 되어야하는데, 문서 1,2 모두 match!!

How

"숫자 + 단위" Pattern 처리

  • 숫자, 단위가 붙어있을 때 오분석이 되는게 문제였으니 이 pattern이 들어왔을 때 처리할 방법이 있을까 했다

  • es에서는 settings에서 regex를 추가하면 간단하게 분석이 가능하다!

"단위 Tokenizer": {
    "type": "pattern",
    "pattern": "(\\d+\\.\\d+|\\d+|단위)",
    "group": 0
}

[분석 결과]
3.5kg => 3.5, kg
20.5cm => 20.5, cm

정해진 pattern에 매칭되는 것은 Boosting!

  • 우선 해당 regex pattern에 걸리면 단위 분석기로 처리한 필드로 query를 날리려고 했다
boolean measureMatches(String query) {
    Pattern pattern = Pattern.compile(".*\\d+(\\.\\d+)?\\s*(단위).*");
    Matcher matcher = pattern.matcher(Optional.ofNullable(query).orElse(""));
    return matcher.matches();
}
  • 원래는 해당 field에 should 조건을 추가하여 'or' query를 날리려고 했는데 성능이 느렸다ㅜ

  • 대신에 elasticsearch에는 filter를 걸어서 해당 필드에 match가 된다면 boost 점수를 올릴 수 있다

"query": {
    "function_score": {
      "query": {
        "bool": {
          ...
        }
      },
      "functions": [
        ...
        {
          "filter": {
            "match_phrase": {
              "단위필드": {
                "query": "숫자+단위 Query",
                "slop": 0,
                "zero_terms_query": "NONE",
                "boost": 1
              }
            }
          },
          "weight": 가중치
        }
      ],
      ...
    }
  },
  ...
  • 'match_phrase'를 사용한 이유는 일반적인 'match'를 사용하면 순서가 바뀌어도 나오게 된다!

common_grams filter

  • es에는 pattern이 일치하는 애들은 묶어서 구로 처리가 가능한 filter가 있다
ex) 3.5kg => 3.5_kg
  • 이렇게 되면 성능, 크기에 있어서 더 유리하다고 한다
    Ref

  • 요런식으로 쓰면 된다

"단위_common_grams": {
    "type": "common_grams",
    "common_words": [적어야 할 단위들],
    "query_mode": true
}

Review

  • 원하던 단위에 해당하는 문서들만 올라와서 이슈가 해결이 됐다

  • 어떠한 패턴이 있을 때 es settings에 type: 'custom'으로 해서 분석기 추가하고 색인시켜 처리한 것이 핵심이었다

  • 특히 분석기 필터 하나 개발하려면, 여간 쉬운게 아니니 이런 방식도 괜찮은 것 같다

0
Subscribe to my newsletter

Read articles from parkhyoungjun directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

parkhyoungjun
parkhyoungjun