Elasticsearch 关键字自动补全的实现

背景

我们经常能看到在各大电商网站搜索关键字的时候,底下下拉框会补全你要搜索的商品,或者类似的商品,有时候甚至连错别字也能纠正过来,其实ElasticSearch也能实现这样的功能

创建索引

首先,能够被自动补全的需要设置索引类型为”completion”,其次,还可以设置自动提示为中文分词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
{
"settings": {
"analysis": {
"analyzer": {
"ik": {
"tokenizer": "ik_max_word"
},
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer"
}
},
"tokenizer": {
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 1,
"max_gram": 30,
"token_chars": [
"letter",
"digit"
]
}
}
}
},
"mappings": {
"knowledge_info": {
"properties": {
"infoId": {
"type": "string"
},
"infoTitle": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word",
"fields": {
"suggest": {
"max_input_length": 30,
"preserve_position_increments": false,
"type": "completion",
"preserve_separators": false,
"analyzer": "ik_max_word"
},
"wordCloud": {
"type": "string",
"analyzer": "ik_smart",
"fielddata":"true"
}
}
},
"infoKeywords": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word",
"fields": {
"suggest": {
"max_input_length": 30,
"preserve_position_increments": false,
"type": "completion",
"preserve_separators": false,
"analyzer": "ik_max_word"
},
"wordCloud": {
"type": "string",
"analyzer": "ik_smart",
"fielddata":"true"
}
}
},
"infoSummary": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word",
"fields": {
"suggest": {
"max_input_length": 30,
"preserve_position_increments": false,
"type": "completion",
"preserve_separators": false,
"analyzer": "ik_max_word"
},
"wordCloud": {
"type": "string",
"analyzer": "ik_smart",
"fielddata":"true"
}
}
},
"infoContent": {
"type": "text",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"propertyAuthor": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"propertyIssueUnit": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"propertyStandardCode": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"propertyLiteratureCategory": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"propertyLcCode": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"propertyLiteratureCode": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"data": {
"type": "text"
},
"attachment.content": {
"type": "text",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word"
},
"auditState": {
"type": "string"
},
"infoType": {
"type": "string"
},
"infoFileUrl": {
"type": "string"
},
"infoFileName": {
"type": "string",
"search_analyzer": "ik_max_word",
"analyzer": "ik_max_word",
"fields": {
"suggest": {
"max_input_length": 60,
"preserve_position_increments": false,
"type": "completion",
"preserve_separators": false,
"analyzer": "ik_max_word"
}
}
},
"createTime": {
"type": "string"
}
}
}
}
}

其中 elasticsearch 需要安装中文分词 ik 插件和附件处理插件 ingest-attachment

Java API 调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* 自动完成提示
* @param search search
* @return MessageBody
*/
public MessageBody autoCompleteKnowledgeInfo(KnowledgeSearch search) {
//设置搜索建议
CompletionSuggestionBuilder infoTitleSuggestion = new CompletionSuggestionBuilder("infoTitle.suggest")
.text(search.getQuery())
.size(6);
CompletionSuggestionBuilder infoKeywordsSuggestion = new CompletionSuggestionBuilder("infoKeywords.suggest")
.text(search.getQuery())
.size(6);
CompletionSuggestionBuilder infoSummarySuggestion = new CompletionSuggestionBuilder("infoSummary.suggest")
.text(search.getQuery())
.size(6);
CompletionSuggestionBuilder infoFileNameSuggestion = new CompletionSuggestionBuilder("infoFileName.suggest")
.text(search.getQuery())
.size(6);
SuggestBuilder suggestBuilder = new SuggestBuilder()
.addSuggestion("标题", infoTitleSuggestion)
.addSuggestion("关键字", infoKeywordsSuggestion)
.addSuggestion("摘要", infoSummarySuggestion)
.addSuggestion("附件",infoFileNameSuggestion);
SearchRequestBuilder searchRequest = client.prepareSearch(ES_KNOWLEDGE_INDEX)
.setFetchSource(false)
.suggest(suggestBuilder);
List<JSONObject> list = new ArrayList<>();

//查询结果
SearchResponse searchResponse = searchRequest.get();

/*没查到结果*/
if (searchResponse.getSuggest() == null) {
return MessageBody.success(list);
}
searchResponse.getSuggest().forEach(entries -> {
String name = entries.getName();
for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry : entries) {
for (Suggest.Suggestion.Entry.Option option : entry.getOptions()) {
JSONObject object = new JSONObject();
object.put("name",name);
object.put("text",option.getText().string());
list.add(object);
}
}
});
return MessageBody.success(list);
}

代码摘取自项目中的部分, 另外前端还可以配合自动完成的插件,最终来实现效果.