news 2026/2/4 14:39:04

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/1/30 20:38:31

15. 实时数据-SpringBoot集成WebSocket

文章目录 前言一、添加依赖&#xff08;Maven&#xff09;二、配置 WebSocket1. 创建 WebSocket 配置类2. 实现 WebSocket 处理器 三、前端测试&#xff08;HTML JS&#xff09;四、启动类&#xff08;标准 Spring Boot 启动类&#xff09;五、可选&#xff1a;使用 STOMP ove…

作者头像 李华
网站建设 2026/1/29 12:57:08

30、FreeBSD 图形界面配置与 KDE 桌面环境使用指南

FreeBSD 图形界面配置与 KDE 桌面环境使用指南 1. X Window 系统配置 X Window 系统为 FreeBSD 提供了类似于 Windows 的图形用户界面。它与窗口管理器协同工作,为用户打造一个高效的工作环境。 1.1 关键配置文件与程序 XF86Config :这是控制 X Window 系统各种属性的文本…

作者头像 李华
网站建设 2026/2/1 8:47:32

项目中绝对位置和相对位置的具体应用解析

这个通常用于有外部库或者文件输入时&#xff0c;使用相对路径可避免代码复制到别的PC端没法使用的情况基础概念&#xff1a;路径分隔符的作用​在文件系统中&#xff0c;路径用于定位文件或目录的位置。反斜杠 \ 是 Windows 系统中的路径分隔符&#xff0c;而正斜杠 / 通常用于…

作者头像 李华
网站建设 2026/1/29 12:05:32

Doris笔记

Doris常用命令&#xff1a; 查看doris 某用户最大连接数 show property for 用户名 like max_user_connections设置单个用户并发数连接&#xff08;立即生效&#xff09; SET PROPERTY FOR 用户名 max_user_connections 500;设置全局的最大并发数连接&#xff08;所有用户的…

作者头像 李华
网站建设 2026/2/3 1:38:15

ThinkingEngine的首个AI原生能力来了!

移动互联网的普及与社交媒体的蓬勃发展&#xff0c;让用户发声的渠道愈发多元且直接。从国内外主流媒体与社区&#xff0c;到企业社群、客户群等私域场景&#xff0c;这些来自用户自发的、实时的对话&#xff0c;往往直接反映了市场对产品的真实感受、未被满足的潜在需求以及正…

作者头像 李华