오늘 다루어볼 내용은 Elasticsearch를 이용한 한글 자동완성 구현이다. 실습을 위한 Elasticsearch는 도커로 세팅을 진행할 것이다. 한글 형태소 분석기가 필요하기 때문에 Elasticsearch docker image를 조금 커스터마이징하여 한글 형태소 분석기(nori)가 설치된 ES 도커 이미지로 도커 컨테이너를 실행시킬 것이다.

 

ES 도커 이미지는 아래 링크를 참조해서 빌드해준다.

 

Elasticsearch - Elasticsearch custom docker image 빌드(엘라스틱서치 커스텀 도커 이미지 생성)

이번에 다루어볼 포스팅은 도커로 ES를 띄우기전에 뭔가 커스텀한 이미지를 만들어서 올릴수없을까 하는 생각에 간단히 ES 기본 이미지에 한글 형태소 분석기(Nori) 플러그인이 설치가된 ES docker image를 커스..

coding-start.tistory.com

docker run
#동의어 사전 사용을 위해 volume mount and data volume mount
> docker run --name elasticsearch -d -p 9200:9200 -p 9300:9300 \
  -e "discovery.type=single-node" \
  -v /home/deploy/elasticsearch_v/dictionary:/usr/share/elasticsearch/data/dictionary \
  -v /home/deploy/elasticsearch_v/data_v:/usr/share/elasticsearch/data \
  es_image_docker_hub

 

Elasticsearch index setting

토크나이저는 한글 형태소분석기인 노리(nori) 형태소 분석기를 이용했고, 자동완성 구현을 위해 edge_ngram filter를 이용하였다.

 

curl --location --request PUT 'localhost:9200/auto_complete' \
--header 'Content-Type: application/json' \
--data-raw '{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "korean_analyzer": {
            "type": "custom",
            "tokenizer": "korean_tokenizer",
            "filter": [
              "lowercase",
              "korean_posfilter",
              "synonym_filter",
              "edge_ngram_filter_front",
              "edge_ngram_filter_back",
              "trim"
            ]
          }
        },
        "tokenizer": {
          "korean_tokenizer" : {
            "type" : "nori_tokenizer",
            "decompound_mode" : "mixed",
            "user_dictionary":"/usr/share/elasticsearch/data/dictionary/user_dict.txt"
          }
        },
        "filter": {
          "edge_ngram_filter_front": {
            "type": "edgeNGram",
            "min_gram": "1",
            "max_gram": "10",
            "side": "front"
          },
          "edge_ngram_filter_back": {
            "type": "edgeNGram",
            "min_gram": "1",
            "max_gram": "10",
            "side": "back"
          },
          "synonym_filter": {
            "type": "synonym",
            "lenient": true,
            "synonyms_path":"/usr/share/elasticsearch/data/dictionary/synonym.txt"
          },
          "korean_posfilter":{
                "type":"nori_part_of_speech",
                "stoptags":[
                    "E",
                    "IC",
                    "J",
                    "MAG",
                    "MM",
                    "NA",
                    "NR",
                    "SC",
                    "SE",
                    "SF",
                    "SP",
                    "SSC",
                    "SSO",
                    "SY",
                    "UNA",
                    "VA",
                    "VCN",
                    "VCP",
                    "XPN",
                    "XR",
                    "XSA",
                    "XSN",
                    "XSV"
                ]
            }
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "auto_complete": {
        "type": "text",
        "analyzer": "korean_analyzer"
      }
    }
  }
}'

 

만약 자동완성을 위한 필드에 색인할때, 생략할 품사들을 지정하기 위해서는 nori_part_of_speech 필터의 stoptags에 넣어주면 된다. 위 설정은 명사류 혹은 동사류만 색인되도록 품사지정을 하였다. 품사(nori_part_of_speech)에 대한 자세한 사항은 아래 링크를 참조하자.

 

 

Elasticsearch - 4.한글 형태소분석기(Nori Analyzer)

엘라스틱서치 혹은 솔라와 같은 검색엔진들은 모두 한글에는 성능을 발휘하기 쉽지 않은 검색엔진이다. 그 이유는 한글은 다른 언어와 달리 조사나 어미의 접미사가 명사,동사 등과 결합하기 ��

coding-start.tistory.com

 

색인 및 한글 자동완성 쿼리
#index document
curl --location --request POST 'http://localhost:9200/auto_complete/_doc' \
--header 'Content-Type: application/json' \
--data-raw '{
    "auto_complete" : "피자 주문할게요"
}'

 

위 요청으로 문서를 색인하고 아래 쿼리를 날려보자.

 

#match query
curl --location --request POST 'http://localhost:9200/auto_complete/_search' \
--header 'Content-Type: application/json' \
--data-raw '{
    "query" : {
        "match" : {
            "auto_complete" : {
                "query" : "피"
            }
        }
    }
}'

 

마지막으로 동의어를 넣기 위해서는 아래와 같이 index를 close 했다가 open해야한다. 아래 요청을 참조하자.

 

#index close
curl --location --request POST 'http://localhost:9200/auto_complete/_close' \
--data-raw ''
 
 
#index open
curl --location --request POST 'http://localhost:9200/auto_complete/_open' \
--data-raw ''

 

여기까지 아주 간단하게 한글 자동 완성을 구현해보았다. 사실 더 최적화할 것도 많고, 자소 분리등을 넣어서 자음만 넣어도 자동완성을 구현할 수도 있지만, 이번 포스팅에서는 그냥 한글 자동완성이 어떤 식으로 구현되는지 간단하게 다루어보았다.

posted by 여성게
: