elasticssearch提供了CompletionSuggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询效率,对于文档中字段的类型有一些约束:
+ 查询类型必须是:completion
+ 字段内容是多个补全词条形成的数组
PUT /test2
{
"mappings": {
"properties": {
"title":{
"type": "completion" #创建字段类型的时候,只能是completion
}
}
}
}
POST /test2/_doc/1
{
"title":["Sony", "WH-1000XM3"] #字段的内容是多词条形成的数组
}
POST test2/_doc/2
{
"title": ["SK-II", "PITERA"]
}
POST test2/_doc/3
{
"title": ["Nintendo", "switch"]
}
# 查询语法,自动补全
GET /test2/_search
{
"suggest": {
"titleSuggest": { #查询的名称
"text": "So", #查询的内容
"completion": { #查询补全的类型
"field": "title", #字段类型
"skip_duplicates": true, #跳过重复的词条
"size": 10 #查询的大小
}
}
}
}
完成一个hotel酒店的es库创建:(创建了两个自定义的分词器)
PUT /hotel
{
"settings": {
"analysis": {
"analyzer": {
"text_anlyzer": {
"tokenizer": "ik_max_word",
"filter": "py"
},
"completion_analyzer": {
"tokenizer": "keyword",
"filter": "py"
}
},
"filter": {
"py": {
"type": "pinyin",
"keep_full_pinyin": false,
"keep_joined_full_pinyin": true,
"keep_original": true,
"limit_first_letter_length": 16,
"remove_duplicated_term": true,
"none_chinese_pinyin_tokenize": false
}
}
}
},
"mappings": {
"properties": {
"id":{
"type": "keyword"
},
"name":{
"type": "text",
"analyzer": "text_anlyzer",
"search_analyzer": "ik_smart",
"copy_to": "all"
},
"address":{
"type": "keyword",
"index": false
},
"price":{
"type": "integer"
},
"score":{
"type": "integer"
},
"brand":{
"type": "keyword",
"copy_to": "all"
},
"city":{
"type": "keyword"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword",
"copy_to": "all"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "text_anlyzer",
"search_analyzer": "ik_smart"
},
"suggestion":{
"type": "completion",
"analyzer": "completion_analyzer",
"search_analyzer": "ik_smart" # 使用这个为了拼音和汉字都可以使用,而不只是拼音
}
}
}
}
java代码查询:
@Test
public void completionTest() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().suggest(new SuggestBuilder().addSuggestion(
"suggestions",
SuggestBuilders.completionSuggestion("suggestion")
.prefix("火")
.size(10)
.skipDuplicates(true)
));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
Suggest suggest = response.getSuggest();
CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
List<CompletionSuggestion.Entry.Option> options = suggestions.getOptions();
for (CompletionSuggestion.Entry.Option option : options) {
String string = option.getText().string();
System.out.println(string);
}
}