[ElasticSearch] 한글 검색 자동완성

Hyebin Lee·2022년 4월 15일
1

ElasticSearch

목록 보기
7/9

참고한 링크

Elasticsearch 자동완성(autocomplete) 구현하기
SuggestAPI 소개
Korean Jaso Analyzer

SuggestAPI

suggestAPI는 사용자가 키워드를 잘못 입력했거나 검색한 결과가 없을 경우 도큐먼트 내에 존재하는 단어를 대상으로 비슷한 키워드를 변경해서 제시하는 교정기능을 제공한다.

  • Term Suggest API : 추천단어 제안
    잘못된 철자에 대해 해당 인덱스의 특정 필드에서 가장 유사한 단어를 추천해주는 오타교정법
  • Completion Suggest API : 자동완성 제안
    사용자가 입력을 완료하기 전에 자동완성을 사용해 검색어를 예측해서 보여주며, 사용자가 검색하는데 도움을 줌
  • Phrase Suggest API : 추천 문장 제안
  • Context Suggest API: 추천 문맥 제안

데이터 준비하기

curl -XPUT 'http://localhost:9200/auto_complete?include_type_name=true&pretty' -H 'Content-Type: application/json' -d '{
  "mappings": {
    "_doc": {
      "properties": {
        "search_string": {
          "type": "completion"
        }
      }
    }
  }
}'

매핑을 통해 completion으로 자동완성을 제안할 필드를 미리 "type" : "completion"으로 지정한다.

completion을 이용한 자동완성

맨앞의 문자가 매칭되는 데이터를 반환한다.
하지만 중간에 매칭되는 검색어는 포함되지 않는다.

curl -XGET 'localhost:9200/auto_complete/_search?pretty' -H 'Content-Type: application/json' -d'{
  "suggest": {
    "search-string-suggest": {
      "prefix": "빨",
      "completion": {
        "field": "search_string"
      }
    }
  }
}'

"prefix"로 맨앞에 매칭할 문자를 지정해준다.

nGram Tokenizer

  • 타입: nGram
  • 옵션
    • min_gram : 토큰의 최소 길이, 기본 = 1

    • max_gram : 토큰의 최대 길이, 기본 = 2

    • token_chars: 지정된 값에 따라 해당하는 형식을 토큰으로 인식한다.

      [letter : a b등 알파벳 문자
      digit : 0 1 2 등의 숫자
      whitespace : 공백과 개행 문자
      punctuation : !과 같은 구두점
      symbol: 특수문자]

min_grammax_gram으로 최대 최소 토큰 길이를 결정하면 해당 범위 내의 토큰이 모두 생성된다.
예를 들어 최대 길이가 3이고 최소길이를 1로 지정한뒤 helloworld라는 입력값을 준다면,
h,e,l,o,w,r,l,d,he,hel, ... 이런식으로 값이 색인된다.

nGram을 사용하면 중요한 필드를 두세 개의 문자만 가지고도 검색할 수 있지만, 그만큼 검색어 토큰 수가 많아지기 때문에 메모리 사용량과 시스템 부하 역시 증가한다.

데이터 준비하기

curl -XPUT 'http://localhost:9200/auto_complete?include_type_name=true&pretty' -H 'Content-Type: application/json' -d '{
  "settings" : {
    "index":{
      "max_ngram_diff": 50,
      "analysis":{
        "analyzer":{
          "my_ngram_analyzer": { //분석기 customize 
            "tokenizer": "my_ngram_tokenizer"
          }
        },
        "tokenizer": { //ngram 토크나이저 customize
          "my_ngram_tokenizer": {
            "type": "ngram",
            "min_gram": "1",
            "max_gram": "10"
          }
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "search_string": {
          "type": "text",
          "fields": { //다중필드
            "ngram": { //ngram 옵션이면
              "type": "text",
              "analyzer": "my_ngram_analyzer" //커스텀한 ngram 토크나이저 분석기로 분석해서 검색하기 
            }
          }
        }
      }
    }
  }
}'

검색 조회

이제 꼭 맨 앞글자가 아니더라도 내용에 "빨" 이 들어가는 데이터는 조회가 모두 된다! Tokenizer로 글자 하나를 단위로 다 쪼개었기 때문이다.

curl -XGET http://localhost:9200/auto_complete/_search?pretty -H 'Content-Type: application/json' -d '{
  "query": {
    "match": {
      "search_string.ngram": "빨"
    }
  }
}'

Korean Jaso Analyzer

https://github.com/netcrazy/elasticsearch-jaso-analyzer
한글 자소단위로 자동완성이 되도록 한다.

  • 자음 단위 검색 가능 (ex. ㅃ -> 빨래방)
  • 영문자 오타 교정 가능(ex. Qkf -> 빨)

ElasticSearch 7.16.2 버전 받기

cd C:\Users\OCS\Desktop\개발\elasticsearch-7.17.2-windows-x86_64\elasticsearch-7.17.2\bin

C:\Users\OCS\Desktop\개발\elasticsearch-7.17.2-windows-x86_64\elasticsearch-7.17.2\bin>sudo elasticsearch-plugin install https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v7.16.2/jaso-analyzer-plugin-7.16.2-plugin.zip
"warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME"
-> Installing https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v7.16.2/jaso-analyzer-plugin-7.16.2-plugin.zip
-> Downloading https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v7.16.2/jaso-analyzer-plugin-7.16.2-plugin.zip
[=================================================] 100%??
-> Failed installing https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v7.16.2/jaso-analyzer-plugin-7.16.2-plugin.zip
-> Rolling back https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v7.16.2/jaso-analyzer-plugin-7.16.2-plugin.zip
-> Rolled back https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v7.16.2/jaso-analyzer-plugin-7.16.2-plugin.zip
Exception in thread "main" java.lang.IllegalArgumentException: Plugin [jaso-analyzer] was built for Elasticsearch version 7.16.2 but version 7.17.2 is running
        at org.elasticsearch.plugins.PluginsService.verifyCompatibility(PluginsService.java:391)
        at org.elasticsearch.plugins.cli.InstallPluginAction.loadPluginInfo(InstallPluginAction.java:831)
        at org.elasticsearch.plugins.cli.InstallPluginAction.installPlugin(InstallPluginAction.java:887)
        at org.elasticsearch.plugins.cli.InstallPluginAction.execute(InstallPluginAction.java:245)
        at org.elasticsearch.plugins.cli.InstallPluginCommand.execute(InstallPluginCommand.java:88)
        at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:77)
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:112)
        at org.elasticsearch.cli.MultiCommand.execute(MultiCommand.java:95)
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:112)
        at org.elasticsearch.cli.Command.main(Command.java:77)
        at org.elasticsearch.plugins.cli.PluginCli.main(PluginCli.java:36)

무시하고 하려고 하니까 다음과 같은 오류가 나네용..😅
다시 엘라스틱서치 버전에 맞춰서 받아줍니다,, (로컬에 대체 엘라스틱서치 zip 파일이 몇개인지)

설치

bin/elasticsearch-plugin install https://github.com/netcrazy/elasticsearch-jaso-analyzer/releases/download/v7.16.2/jaso-analyzer-plugin-7.16.2-plugin.zip

설정 및 인덱스 생성

curl -XPUT -H 'Content-Type: application/json' http://localhost:9200/jaso/ -d '{
  "settings": {
    "index": {
      "analysis": {
        "filter": {
          "suggest_filter": {
            "type": "edge_ngram",
            "min_gram": 1,
            "max_gram": 50
          }
        },
        "tokenizer": {
          "jaso_search_tokenizer": {
            "type": "jaso_tokenizer",
            "mistype": true,
            "chosung": false
          },
          "jaso_index_tokenizer": {
            "type": "jaso_tokenizer",
            "mistype": true,
            "chosung": true
          }
        },
        "analyzer": {
          "suggest_search_analyzer": {
            "type": "custom",
            "tokenizer": "jaso_search_tokenizer"
          },
          "suggest_index_analyzer": {
            "type": "custom",
            "tokenizer": "jaso_index_tokenizer",
            "filter": [
              "suggest_filter"
            ]
          }
        }
      }
    }
  }
}'

인덱스 매핑

curl -XPUT -H 'Content-Type: application/json' http://localhost:9200/jaso/_mapping/test -d '{
  "properties": {
    "name": {
      "type": "text",
      "store": true,
      "analyzer": "suggest_index_analyzer",
      "search_analyzer": "suggest_search_analyzer"
    }
  }
}'
  • 이 과정에서 아래 오류가 났다
  "type": "illegal_argument_exception",
        "reason": "Types cannot be provided in get mapping requests, unless include_type_name is set to true."

매핑으로 필드의 타입을 설정해줄 때는 include_type_name 파라미터(매개변수)를 true로 주라고 한다

하라는대로 하니까 잘 매핑이 되었다!

문서 생성

curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/jaso/test?pretty=true -d '{
    "name":"최일규 Hello"
}'

curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/jaso/test?pretty=true -d '{
    "name":"초아"
}'

문서 검색

curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/jaso/test/_search?pretty=true -d '{
    "query" : {
        "match" : { "name" : "초" }
    }
}'

curl -XPOST -H 'Content-Type: application/json' http://localhost:9200/jaso/test/_search?pretty=true -d '{
    "query" : {
        "match" : { "name" : "ㅊㅇㄱ" }
    }
}'

0개의 댓글