1.问题起因
最近在做项目的时候遇到了一个问题,就是在做搜索功能的时候,需要像各类搜索网站和电商网站一样,可以在输入第一个字或者拼音的时候提示出后续数据库内存在的内容供用户自行选择或者继续输入,如下:
因为用的是ElasticSearch,所以在网上给出的答案是:
那么类似的功能在Elasticsearch里如何实现呢? 答案就在Suggesters API。 Suggesters基本的运作原理是将输入的文本分解为token,然后在索引的字典里查找相似的term并返回。 根据使用场景的不同,Elasticsearch里设计了4种类别的Suggester,分别是:
Term Suggester
Phrase Suggester
Completion Suggester
Context Suggester
精准程度上(Precision)看: Completion > Phrase > term, 而召回率上(Recall)则反之。从性能上看,Completion Suggester是最快的,如果能满足业务需求,只用Completion Suggester做前缀匹配是最理想的。 Phrase和Term由于是做倒排索引的搜索,相比较而言性能应该要低不少,应尽量控制suggester用到的索引的数据量,最理想的状况是经过一定时间预热后,索引可以全量map到内存。
遂决定用Completion Suggester,后续还可以根据需要添加Phrase Suggester,当需要用户填写错误时提供近似的提示词。但是翻了一圈下来发现要不然就是只有直接讲ElasticSearch语法的,要不然就是用6.x版本时期的单体插件的教程,让已经使用了和SpringBoot集成版本的我十分捉急,又找不到集成版的官方文档或者教程一类,只能自己慢慢摸索,在这里就重新记录一下如何操作这个事情。
2.前期准备
这里还是要稍微说一下,ElasticSearch的版本是7.6.1,集成在SpringBoot2.3.2版本上。
-
导入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
-
配置类
@Configuration public class ElasticSearchClientConfig { @Value("${el.host}") private String host; @Value("${el.port}") private int port; @Bean public RestHighLevelClient restHighLevelClient () { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost(host,port,"http")) ); return client; } }
3.操作
-
首先是创建索引,因为需要使用suggest,索引属性类型,type=Completion,不然会报错:
type=illegal_argument_exception, reason=Field [suggest] is not a completion suggest field]
//由于用到suggest所以需要手动创建一下索引对suggest赋值类型 CreateIndexRequest createIndexRequest = new CreateIndexRequest("news"); Map<String, Object