Skip to main content

Elasticsearch 7.3 활용해보기 #3

생각해보니 이 앞전에 해보았던 자연어 처리기를 활용하여 인덱스에 세팅해보니 뭔가가 부족함이 있어 보입니다. 무슨 말이냐면, 붙어있는 단어들을 처리하지 못해서 mysql 에서의 field like ‘%이장님%’ 과 같은 단어를 처리하지 못하였습니다.

그래서 인덱스 생성시에 tokenizer 등을 추가적으로 지정해줄 필요가 있습니다. -_-

#2 에서 봤던 기본 분석기로는 세팅을 바꿀 수가 없어서 분석기가 포함된 인덱스를 만들어봅시다. 간단한 테스트를 할 때는 kibana의 console을 통해서 할 수 있습니다.

사용된 코드는 다음과 같습니다. 이렇게하면 korean_dict 인덱스가 생성되며, 이 인덱스의 설정에 따라 인덱스에 추가되는 문서들이 분석되게 됩니다. (원래 하고자하는 테스트도 할수 있습니다. -_-) 한글을 인덱스 만들때 쓸수 있음으로 아래의 세팅 내용은 잘 기억해둬야 될거 같습니다. (그러기엔 좀 길지만;;; 복사해서… … )

PUT korean_dict
{
  "settings":{
      "number_of_shards":1,
      "number_of_replicas":0,
      "index":{
        "analysis":{
          "tokenizer":{
            "nori_tokenizer_mixed_dict":{
              "type":"nori_tokenizer",
              "decompound_mode":"mixed",
              "user_dictionary":"userdict_ko.txt"
            }
          },
          "analyzer": {
            "korean":{
              "type":"custom",
              "tokenizer":"nori_tokenizer_mixed_dict",
              "filter":[
                "nori_readingform","lowercase",
                "nori_part_of_speech_basic"]
              }
            },
            "filter":{
              "nori_part_of_speech_basic":{
                "type":"nori_part_of_speech",
                "stoptags":["E","IC","J","MAG","MAJ","MM","SP","SSC","SSO","SC","SE","XPN","XSA","XSN","XSV","UNA","NA","VSV"]
            }
          }
        }
      }
    }
}

여기서 userdict_ko.txt 파일이 있습니다. 기본적인 nori 기능 이외에 추가적인 필터들 nori_readingform, nori_part_of _speech_basic 등을 추가하고 사용자 사전도 추가되었습니다.

사용자 사전은 다음 경로에 있습니다.

/etc/elasticsearch/userdict_ko.txt

사용자 사전의 용도는 인덱싱을 위해 잘라지지 않는 단어들에 대한 분리를 정의 할 수 있습니다. 전체 단어와 그 단어가 잘라진 모양을 기록해두면 됩니다.

고양이톱밥 고양이 톱밥
한글형태소분석기 한글 형태소 분석기
대한민국임시정부수립기념일 대한민국 임시정부 수립 기념일
우리동내 우리 동내

..... 등등 단어의 확장으로 ... 
도스르다 무슨 일을 하려고 벌려서 마음을 가다듬다(X 이건안됨)

반드시 해당하는 단어가 분리된 형태여야만 합니다.
(다른걸 집어 넣었떠니 오류가 -_-… )

뭐 어쨌뜬 이렇게해서 다시 토큰 분석 쿼리를 날려보면..

GET korean_dict/_analyze
{
  "analyzer": "korean",
  "text": "대한민국임시정부수립기념일"
}

단어분리가 사전에 정의한 단어를 포함하여 파싱되는 것을 확인 할 수 있습니다.

{
  "tokens" : [
    {
      "token" : "대한민국",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "word",
      "position" : 0,
      "positionLength" : 2
    },
    {
      "token" : "대한",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "민국",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "임시",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "정부",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "수립",
      "start_offset" : 8,
      "end_offset" : 10,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "기념일",
      "start_offset" : 10,
      "end_offset" : 13,
      "type" : "word",
      "position" : 5,
      "positionLength" : 2
    },
    {
      "token" : "기념",
      "start_offset" : 10,
      "end_offset" : 12,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "일",
      "start_offset" : 12,
      "end_offset" : 13,
      "type" : "word",
      "position" : 6
    }
  ]
}

그렇다면 원래 분석기는 사용자 사전에 해당하는 단어가 검색되지 않습니다.
(#2에 사용된 쿼리를 이용하였습니다.)

{
  "tokens" : [
    {
      "token" : "대한",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "민국",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "임시",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "정부",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "수립",
      "start_offset" : 8,
      "end_offset" : 10,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "기념",
      "start_offset" : 10,
      "end_offset" : 12,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "일",
      "start_offset" : 12,
      "end_offset" : 13,
      "type" : "word",
      "position" : 6
    }
  ]
}

만약에 실무에 활용한다면, 사용자 사전에 단어를 추가하여 검색되지 않는 단어를 대응 하면 되지 않을까요!

오늘도 여기까지 -_- …

꾸준히 계속 적어봐야겠네요…

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.