Nori 적용하기

한글 형태소 분석기 Nori 적용하기

https://www.elastic.co/guide/en/elasticsearch/plugins/6.4/analysis-nori.html

Nori 형태소 분석기

루씬 프로젝트에서 공식적으로 제공되는 한글 형태소 분석기 6.4버전에서 공식적으로 릴리즈 됨

기존 형태소 분석기에 비해 30% 이상 빠르고 메모리 사용량도 현저하게 줄었으며, 시스템 전반에 영향을 주지 않게 최적화 됐다.

라이센서는 아파리라이선스 2.0 으로 채택

Nori는 서드파티 플러그 인과 달리 루씬에서 공식적으로 지원

$elasticsearch-plugun install analysis-nori

Nori 분석기

  • nori_tokenizer
  • nori_part_of_speech : 토큰 필터
  • nori_readingform : 토큰 필터

Nori_tokenizer

decompound_mode

  • none : no decomposition (분해 하지 않음)

    가거도항
    가곡역
  • discard :기본 값

    가곡역 => 가곡, 역
  • mixed : 기본적인 분할과 오리지날 단어를 함꼐 출력

    가곡역 => 가곡역, 가곡, 역

user_dictionary

nori tokenizer는 me cab-ko-dic dictionary( https://bitbucket.org/eunjeon/mecab-ko-dic/src/master/) (은전한잎)를 기본적으로 사용한다.

다음과 같은 포맷이 될수 있다.

<token> [<token1> ... <token n>]

첫번째의 토큰은 필수이며, 사전에 추가해야하는 사용자 지정 명사를 나타낸다.

복합 명사의 경우에는 첫번째 토큰( [< token1> …]) 을 제공한다.

복합 명사의 세분화는 decompound_mode 설정에 의해 제어된다.

$ES_HOME/conf/userdic_ko.txt 에 아래와 같은 데이터를 입력한다.

삼성전자 삼성 전자

userdic_ko.txt 파일에 위와 같이 설정을 하여도 decompound_mode 에 따라 영향을 받는다.

mixed 를 사용하면 복합 명사의 토큰을 분리한 거 + 복함명사를 구성하는 token 이 출력되며,

discard를 사용하면 삼성, 전자 만 출력

none을 사용하면 삼성전자 만 출력 될 것이다.

예제 테스트

analyzer

: 토크나이저를 활용하여 데이터를 테스트 해보자!!

PUT nori_sample
{
  "settings": {
    "index": {
      "analysis": {
        "tokenizer": {
          "nori_user_dict": {
            "type": "nori_tokenizer",
            "decompound_mode": "mixed",
            "user_dictionary": "userdict_ko.txt"
          }
        },
        "analyzer": {
          "my_analyzer": {
            "type": "custom",
            "tokenizer": "nori_user_dict"
          }
        }
      }
    }
  }
}

My_analyze 라는 사용자 분석기를 만들었다. 내부적으로는 은전한잎이 추가되어있음

쿼리

아래의 쿼리는 유저가 만든 유저 사전을 통해서 analyzer를 적용하여 테스트를 해보는 것이다.

POST nori_sample/_analyze
{
  "analyzer": "my_analyzer",
  "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
    }
  ]
}

결과는 잘나온다.

테스트가 아닌 검색을 해보자 !!

Term 쿼리를 사용하여 전자 만 사용했을 경우에는 잘 될까??

POST nori_sample/_doc/
{
  "title": "삼성전자"
}

GET nori_sample/_search
{
  "query":{
    "terms":{
      "title": ["전자"]
    }
  }
}
GET nori_sample/_search
{
  "query": {
    "bool": {
      "must": {
        "term": {
          "title": "삼성전자"
        }
      }
    }
  }
}
POST nori_sample/_mapping/_doc
{
  "properties": {
    "full_text": {
      "type": "text"
    }
  }
}

POST nori_sample/_doc
{
  "full_text":"삼성전자"
}

맵핑 파일의 타입까지 변경하고 찾아 보았다 하지만 다 검색이 안된다.

왜 검색이 안되나 했는데 이유는 다음과 같다 ..사용자 추가 analyzer는 은전한잎 이기 때문에 .......


term 쿼리
query: term: 필드: 질의어
term 필터와 똑같이 동작하는데, term 필터와는 달리 연관성 점수를 매긴다.

예) 키워드가 민주노총인 문서

GET /_search
{
  "query": {
    "term": {
      "keyword": "민주노총"
    }
  }
}
이것 대신 match 쿼리를 사용하는 것이 좋다. term 쿼리는 저수준의 쿼리로 직접 사용할 필요가 없다. 그리고 은전한닢 분석기로 분석된 한글은 분석을 거치지 않은 한글과는 텀이 일치하지 않으므로 분석을 돌린 필드에는 term 쿼리로 선택이 안 된다.

참고 : https://bakyeono.net/post/2016-08-20-elasticsearch-querydsl-basic.html#%ED%95%84%ED%84%B0%EC%9D%98-%EC%BA%90%EC%8B%9C-%EC%9B%90%EB%A6%AC

'BackEnd > ElasticSearch' 카테고리의 다른 글

[Elasticsearch] failed to obtain node locks  (0) 2019.06.21
SuggestAPI 소개  (0) 2019.06.10
Nori 사용 해서 노래 가사 검색하기  (0) 2019.06.10
Elasticsearch 모니터링 툴  (0) 2019.03.04
Elasticsearch logger  (0) 2019.02.25

+ Recent posts