news 2026/4/16 13:29:05

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/10 19:15:01

kotaemon日志系统全解析:实现操作透明化监控

Kotaemon日志系统全解析&#xff1a;实现操作透明化监控 在企业级AI系统的实际部署中&#xff0c;一个令人头疼的场景是&#xff1a;用户报告“机器人突然不回答问题了”&#xff0c;而运维人员面对空白的响应和沉默的日志束手无策。这种“黑盒式”运行不仅延误故障排查&#x…

作者头像 李华
网站建设 2026/4/8 19:51:51

小程序项目之使命召唤游戏助手源代码(java+vue+小程序+mysql)

大家好我是风歌&#xff0c;曾担任某大厂java架构师&#xff0c;如今专注java毕设领域。今天要和大家聊的是一款java小程序项目——使命召唤游戏助手小程序。项目源码以及远程配置部署相关请联系风歌&#xff0c;文末附上联系信息 。项目简介&#xff1a;项目包括系统首页&…

作者头像 李华
网站建设 2026/4/14 1:02:01

31、深入了解KDE桌面环境:功能、操作与定制

深入了解KDE桌面环境:功能、操作与定制 1. KDE桌面基础操作 KDE桌面提供了一系列实用的操作选项,方便用户管理窗口和图标: - 窗口层叠(Cascade windows) :与微软Windows的窗口层叠功能类似,它能将桌面上的窗口以层叠样式排列。 - 图标排列(Line up icons) :此…

作者头像 李华
网站建设 2026/4/9 23:34:12

40、FreeBSD 文件共享与资源指南

FreeBSD 文件共享与资源指南 1. Samba 共享基础 Samba 允许客户端通过请求主机的 IP 地址获得响应,从而直接向服务器发起 SMB 请求。它类似于 DNS(将通用名称映射到直接地址),也与 ARP 有很多共同之处(通过广播名称请求在局域网中运行,而非向指定的中央名称服务器请求)…

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

【读书笔记】《布鲁克林有棵树》

《布鲁克林有棵树》书籍解读&#xff1a;贫困家庭如何培养出极具安全感的孩子 这是一本经典文学名著&#xff0c;作者贝蒂史密斯&#xff08;Betty Smith&#xff09;于1896年出生&#xff0c;1972年去世。该书出版于1943年&#xff0c;本质上是作者的人生侧写与自传性小说。故…

作者头像 李华