티스토리 뷰

이 글은 김종민(kimjmin@gmail.com)님의 글입니다. 무단 복제/수정을 금합니다.

 

Elasticsearch는 빠른 검색을 위해 검색에 사용될 텀 들을 미리 분리해서 역 인덱스에 저장합니다. 하지만 과학 용어집 검색 같은 특정한 사용 사례에 따라 텀이 아닌 단어의 일부만 가지고도 검색해야 하는 기능이 필요한 경우도 있습니다. RDBMS의 LIKE 검색 처럼 사용하는 wildcard 쿼리나 regexp (정규식) 쿼리도 지원을 하지만, 이런 쿼리들은 메모리 소모가 많고 느리기 때문에 Elasticsearch의 장점을 활용하지 못합니다. 이런 사용을 위해 검색 텀의 일부만 미리 분리해서 저장을 할 수 있는데 이렇게 단어의 일부를 나눈 부위를 NGram 이라고 합니다. 보통은 unigram(유니그램 – 1글자), bigram(바이그램 - 2자) 등으로 부릅니다.

 

Elasticsearch는 NGram을 처리하는 토큰 필터를 제공하며 설정은 "type": "nGram" 으로 합니다. "house" 라는 단어를 2 글자의 NGram (bigram) 으로 처리하면 다음과 같이 "ho", "ou", "us", "se" 총 4개의 토큰들이 추출됩니다. ngram 토큰필터를 사용하면 이렇게 2글자씩 추출된 텀들이 모두 검색 토큰으로 저장됩니다. 이제 이 인덱스의 경우에는 검색어를 "ho" 라고만 검색을 해도 house 가 포함된 도큐먼트들이 검색이 됩니다.

 

무단 복제/수정 금지

주의 : ngram 토큰필터를 사용하면 저장되는 텀의 갯수도 기하급수적으로 늘어나고 검색어를 "ho"로 검색 했을 때 house, shoes 처럼 검색 결과를 예상하기 어렵기 때문에 일반적인 텍스트 검색에는 사용하지 않는 것이 좋습니다. ngram을 사용하기 적합한 사례는 카테고리 목록이나 태그 목록과 같이 전체 개수가 많지 않은 데이터 집단에 자동완성 같은 기능을 구현하는 데에 적합합니다.

ngram 토큰 필터에는 min_gram (디폴트 1), max_gram (디폴트 2) 옵션이 있습니다. 짐작할 수 있듯이 최소, 최대 문자수의 토큰을 구분하는 단위입니다. house를 "min_gram": 2, "max_gram": 3 으로 설정하면 다음과 같이 분석되어 총 7개의 토큰을 저장합니다.

무단 복제/수정 금지

다음은 my_ngram 인덱스에 "min_gram": 2, "max_gram": 3 인 my_ngram_f 토큰필터를 만들고 house 를 분석하는 예제입니다.

 

my_ngram 인덱스 생성
PUT my_ngram
{
  "settings": {
    "analysis": {
      "filter": {
        "my_ngram_f": {
          "type": "nGram",
          "min_gram": 2,
          "max_gram": 3
        }
      }
    }
  }
}

 

Request

my_ngram_f 토큰필터로 "house" 분석
GET my_ngram/_analyze
{
  "tokenizer": "keyword",
  "filter": [
    "my_ngram_f"
  ],
  "text": "house"
}

Response

my_ngram_f 토큰필터로 "house" 분석 결과
{
  "tokens" : [
    {
      "token" : "ho",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "hou",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "ou",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "ous",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "us",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "use",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "se",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "word",
      "position" : 0
    }
  ]
}
댓글
댓글쓰기 폼
공지사항
Total
248,450
Today
825
Yesterday
1,065
링크
«   2022/10   »
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
글 보관함