elasticsearch提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。
为了提高补全查询的效率,对于文档中字段的类型有一些约束:
参与补全查询的字段必须是completion类型。
字段的内容一般是用来补全的多个词条形成的数组。
查询的DSL语句如下:
// 自动补全查询
GET /test/_search
{"suggest": {//表示是自动补全查询,固定写法"title_suggest": {//给查询起的名字,自定义"text": "s", // 关键字,查询s开头的数据"completion": {"field": "title", // 补全查询的字段,在哪个字段查询"skip_duplicates": true, // 跳过重复的"size": 10 // 获取前10条结果}}}
}
1.确认索引库结构和使用的分词器,建议:创建倒排索引时,使用ik和拼音分词器,查询时使用ik分词器
示例:
// 酒店数据索引库
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": "keyword"}}}
}
2.索引库添加一个新字段suggestion,类型为completion类型
3.在对应的实体类中添加suggestion字段
4.代码实现
自动补全查询的DSL对应的JavaAPI
自动补全的结果的DSL对应的JavaAPI
根据前端的请求,完善controller层接口:
@GetMapping("suggestion")
public List getSuggestions(@RequestParam("key") String prefix) {return hotelService.getSuggestions(prefix);
}
service层:
List getSuggestions(String prefix);
serviceimpl层:
@Override
public List getSuggestions(String prefix) {try {// 1.准备RequestSearchRequest request = new SearchRequest("hotel");// 2.准备DSLrequest.source().suggest(new SuggestBuilder().addSuggestion("suggestions",// 查询的名称,自定义SuggestBuilders.completionSuggestion("suggestion")//自动补全的字段名.prefix("北京")//关键字,查询以北京开头的数据.skipDuplicates(true)// 跳过重复词条.size(10)//显示的词条数量));// 3.发起请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析结果Suggest suggest = response.getSuggest();// 4.1.根据补全查询名称,获取补全结果CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");// 4.2.获取optionsList options = suggestions.getOptions();// 4.3.遍历List list = new ArrayList<>(options.size());for (CompletionSuggestion.Entry.Option option : options) {String text = option.getText().toString();list.add(text);}return list;} catch (IOException e) {throw new RuntimeException(e);}
}