Elasticsearch 자동완성(autocomplete) 구현하기
SuggestAPI 소개
Korean Jaso Analyzer
suggestAPI는 사용자가 키워드를 잘못 입력했거나 검색한 결과가 없을 경우 도큐먼트 내에 존재하는 단어를 대상으로 비슷한 키워드를 변경해서 제시하는 교정기능을 제공한다.
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"으로 지정한다.
맨앞의 문자가 매칭되는 데이터를 반환한다.
하지만 중간에 매칭되는 검색어는 포함되지 않는다.
curl -XGET 'localhost:9200/auto_complete/_search?pretty' -H 'Content-Type: application/json' -d'{
"suggest": {
"search-string-suggest": {
"prefix": "빨",
"completion": {
"field": "search_string"
}
}
}
}'
"prefix"로 맨앞에 매칭할 문자를 지정해준다.
min_gram
: 토큰의 최소 길이, 기본 = 1
max_gram
: 토큰의 최대 길이, 기본 = 2
token_chars
: 지정된 값에 따라 해당하는 형식을 토큰으로 인식한다.
[letter : a b등 알파벳 문자
digit : 0 1 2 등의 숫자
whitespace : 공백과 개행 문자
punctuation : !과 같은 구두점
symbol: 특수문자]
min_gram
과 max_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": "빨"
}
}
}'
https://github.com/netcrazy/elasticsearch-jaso-analyzer
한글 자소단위로 자동완성이 되도록 한다.
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" : "ㅊㅇㄱ" }
}
}'