news 2026/4/19 21:41:46

13. 搜索引擎-ES-自动补全

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
13. 搜索引擎-ES-自动补全

文章目录

  • 前言
  • 一、概念
  • 二、拼音分词器
  • 三、自定义拼音分词器
  • 四、自动补全查询
  • 五、自动补全嵌入项目
    • 5.1 修改索引库映射结构
    • 5.2 修改实体类
    • 5.3 重新导入数据
    • 5.4 自动补全的JavaAPI

前言

ES自动补全

当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项。这种根据用户输入的字母,提示完整词条的功能,就是自动补全了。


一、概念

当用户在搜索框输入字符时,我们应该提示出与该字符有关的搜索项。这种根据用户输入的字母,提示完整词条的功能,就是自动补全了。

① 设置创建索引库(设置一个自动补全字段,类型为:completion)

② 重新插入数据

③ 查询(查询时要设置这个自动补全操作的名称,并且指定那个类型为completion的字段)

④ 分解结果(结果也需要根据之前设置这个自动查询操作的名称来取)

二、拼音分词器

下载拼音分词器记得版本要和ES对应,不对应会报错

要实现根据字母做补全,就必须对文档按照拼音分词。在GitHub上恰好有Elasticsearch的拼音分词插件。地址:https://github.com/medcl/Elasticsearch-analysis-pinyin

课前资料中也提供了拼音分词器的安装包:

安装方式与IK分词器一样,分三步:

​ ①解压

​ ②上传到虚拟机中,Elasticsearch的plugin目录

​ ③重启Elasticsearch

​ ④测试

详细安装步骤可以参考IK分词器的安装过程。

三、自定义拼音分词器

如何使用拼音分词器?

  • ①下载pinyin分词器

  • ②解压并放到Elasticsearch的plugin目录

  • ③重启即可

如何自定义分词器?

  • ①创建索引库时,在settings中配置,可以包含三部分

  • ②character filter

  • ③tokenizer

  • ④filter

拼音分词器注意事项?

  • 为了避免搜索到同音字,搜索时不要使用拼音分词器

默认的拼音分词器会将每个汉字单独分为拼音,而我们希望的是每个词条形成一组拼音,需要对拼音分词器做个性化定制,形成自定义分词器。官网文档查询地址:https://github.com/medcl/Elasticsearch-analysis-pinyin

Elasticsearch中分词器(analyzer)的组成包含三部分:

  • character filters:在tokenizer之前对文本进行处理。例如删除字符、替换字符
  • tokenizer:将文本按照一定的规则切割成词条(term)。例如keyword,就是不分词;还有ik_smart
  • tokenizer filter:将tokenizer输出的词条做进一步处理。例如大小写转换、同义词处理、拼音处理等

文档分词时会依次由这三部分来处理文档:

声明自定义分词器的语法如下:

PUT/test{"settings":{"analysis":{"analyzer":{// 自定义分词器"my_analyzer":{// 分词器名称"tokenizer":"ik_max_word","filter":"py"}},"filter":{// 自定义tokenizer filter"py":{// 过滤器名称"type":"pinyin",// 过滤器类型,这里是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":{"name":{"type":"text","analyzer":"my_analyzer","search_analyzer":"ik_smart"}}}}

测试:

四、自动补全查询

三步骤:

① 创建索引库

② 插入数据

③ 查询的DSL语句

Elasticsearch提供了Completion Suggester查询来实现自动补全功能。这个查询会匹配以用户输入内容开头的词条并返回。为了提高补全查询的效率,对于文档中字段的类型有一些约束:

  • 参与补全查询的字段必须是completion类型。

  • 字段的内容一般是用来补全的多个词条形成的数组。

比如,一个这样的索引库:

// 创建索引库PUTtest{"mappings":{"properties":{"title":{"type":"completion"}}}}

然后插入下面的数据:

// 示例数据POSTtest/_doc{"title":["Sony","WH-1000XM3"]}POSTtest/_doc{"title":["SK-II","PITERA"]}POSTtest/_doc{"title":["Nintendo","switch"]}

查询的DSL语句如下:

// 自动补全查询GET/test/_search{"suggest":{"title_suggest":{//设置这个自动查询操作的名称"text":"s",// 关键字"completion":{"field":"title",// 补全查询的字段名"skip_duplicates":true,// 跳过重复的"size":10// 获取前10条结果}}}}

五、自动补全嵌入项目

5.1 修改索引库映射结构

重点注意:

① all、name字段等要 分词设置为自定义分词器(“analyzer”: “text_anlyzer”)(一般要分词,然后再对分词后的词语进行拼音处理),查询设置为最精简分词器(“search_analyzer”: “ik_smart”)

② 设置一个自动补全字段(如 suggestion) 类型必须为:completion,并且使用自定义分词器(一般不分词直接对整个词语进行拼音处理)

先删除之前的索引库,再设置如下:

// 酒店数据索引库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"}}}}

5.2 修改实体类

类型为completion的字段需要在改造方法里做组装

HotelDoc中要添加一个字段,用来做自动补全,内容可以是酒店品牌、城市、商圈等信息。按照自动补全字段的要求,最好是这些字段的数组。

因此我们在HotelDoc中添加一个suggestion字段,类型为List<String>,然后将brand、city、business等信息放到里面。

代码如下:

packagecn.itcast.hotel.pojo;importlombok.Data;importlombok.NoArgsConstructor;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Collections;importjava.util.List;@Data@NoArgsConstructorpublicclassHotelDoc{privateLongid;privateStringname;privateStringaddress;privateIntegerprice;privateIntegerscore;privateStringbrand;privateStringcity;privateStringstarName;privateStringbusiness;privateStringlocation;privateStringpic;privateObjectdistance;privateBooleanisAD;privateList<String>suggestion;publicHotelDoc(Hotelhotel){this.id=hotel.getId();this.name=hotel.getName();this.address=hotel.getAddress();this.price=hotel.getPrice();this.score=hotel.getScore();this.brand=hotel.getBrand();this.city=hotel.getCity();this.starName=hotel.getStarName();this.business=hotel.getBusiness();this.location=hotel.getLatitude()+", "+hotel.getLongitude();this.pic=hotel.getPic();// 组装suggestionif(this.business.contains("/")){// business有多个值,需要切割String[]arr=this.business.split("/");// 添加元素this.suggestion=newArrayList<>();this.suggestion.add(this.brand);Collections.addAll(this.suggestion,arr);}else{this.suggestion=Arrays.asList(this.brand,this.business);}}}

5.3 重新导入数据

先删除数据,再重新执行之前编写的导入数据功能,可以看到新的酒店数据中包含了suggestion:

5.4 自动补全的JavaAPI

示例:(这两幅图有点乱,看不懂就忽略)

查询代码如下:

解析结果代码如下:

1)在cn.itcast.hotel.web包下的HotelController中添加新接口,接收新的请求:

@GetMapping("suggestion")publicList<String>getSuggestions(@RequestParam("key")Stringprefix){returnhotelService.getSuggestions(prefix);}

2)在cn.itcast.hotel.service包下的IhotelService中添加方法:

List<String>getSuggestions(Stringprefix);

3)在cn.itcast.hotel.service.impl.HotelService中实现该方法:

@OverridepublicList<String>getSuggestion(Stringprefix){try{// 1.准备RequestSearchRequestrequest=newSearchRequest("hotel");// 2.准备DSLrequest.source().suggest(newSuggestBuilder().addSuggestion("hotelSuggestion",//设置这个自动补全操作的名称SuggestBuilders.completionSuggestion("suggestion")//类型为completion的字段名.prefix(prefix).skipDuplicates(true).size(10)));// 3.发起请求SearchResponseresponse=client.search(request,RequestOptions.DEFAULT);// 4.解析结果Suggestsuggest=response.getSuggest();// 4.1.根据补全查询名称,获取补全结果(这里的参数是索引库里类型为completion的字段名)CompletionSuggestionsuggestions=suggest.getSuggestion("hotelSuggestion");//之前设置的这个自动查询操作的名称// 4.2.获取optionsList<CompletionSuggestion.Entry.Option>options=suggestions.getOptions();// 4.3.遍历List<String>list=newArrayList<>(options.size());for(CompletionSuggestion.Entry.Optionoption:options){Stringtext=option.getText().toString();list.add(text);}returnlist;}catch(IOExceptione){thrownewRuntimeException(e);}}

本文的引用仅限自我学习如有侵权,请联系作者删除。
参考知识
ElasticSearch (ES从入门到精通一篇就够了)
ELK介绍


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 4:45:46

FaceFusion局域网访问设置方法

FaceFusion局域网访问设置方法 在使用 FaceFusion 这类基于 Web UI 的人脸替换与增强工具时&#xff0c;很多用户会遇到一个常见需求&#xff1a;希望在局域网内的其他设备&#xff08;如平板、手机或其他电脑&#xff09;上也能访问和操作 FaceFusion 界面。这在团队协作、远…

作者头像 李华
网站建设 2026/4/17 17:53:49

Stable Diffusion 3.5 发布:图像生成新突破

Stable Diffusion 3.5 FP8 发布&#xff1a;图像生成效率的新拐点 你有没有遇到过这种情况&#xff1f;明明写好了精炼的提示词&#xff0c;构图、光影、风格都描述得清清楚楚&#xff0c;结果模型要么“选择性失明”&#xff0c;要么生成一堆模糊拼贴——更别提在16GB显存的消…

作者头像 李华
网站建设 2026/4/18 13:28:24

未来的App不再需要菜单栏?

2013年&#xff0c;电影《她》&#xff08;Her&#xff09;描绘了一个令人着迷又略带不安的未来&#xff1a;人类与操作系统通过自然语言持续对话&#xff0c;AI不仅理解语义&#xff0c;还能感知情绪、记住过往、主动推理——它不再是工具&#xff0c;而是一个“认知伙伴”。 …

作者头像 李华
网站建设 2026/4/18 18:25:50

Flutter 勇闯2D像素游戏之路(三):人物与地图元素的交互

Flutter 勇闯2D像素游戏之路&#xff08;一&#xff09;&#xff1a;一个 Hero 的诞生 Flutter 勇闯2D像素游戏之路&#xff08;二&#xff09;&#xff1a;绘制加载游戏地图 Flutter 勇闯2D像素游戏之路&#xff08;三&#xff09;&#xff1a;人物与地图元素的交互 前言 在…

作者头像 李华
网站建设 2026/4/17 21:32:28

用PyTorch实现轴承故障诊断:多尺度卷积+注意力机制实战

基于多尺度卷积神经网络的滚动轴承故障诊断 针对传统方法在难以自适应提取滚动轴承有效故障特征信息的问题&#xff0c;提出了一种多尺度卷积神经网络的滚动轴承故障诊断方法。 首先&#xff0c;构建了多尺度特征融合模块自适应提取故障样本不同感受野下的特征表示&#xff0c;…

作者头像 李华
网站建设 2026/4/16 14:12:40

基于matlab的凸轮轮廓的设计计算与绘图 计算此结构的最优化参数,根据其原理输出推程和回程的...

基于matlab的凸轮轮廓的设计计算与绘图 计算此结构的最优化参数&#xff0c;根据其原理输出推程和回程的最大压力角、最小曲率半径等相关结果。 程序已调通&#xff0c;可直接运行。打开MATLAB的脚本编辑器&#xff0c;迎面扑来的是熟悉的蓝色界面。咱们今天要折腾的这个凸轮设…

作者头像 李华