详解SpringCloud微服务技术栈:深入ElasticSearch(2)——自动补全、拼音搜索

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:详解SpringCloud微服务技术栈:深入ElasticSearch(1)——数据聚合
📚订阅专栏:微服务技术全家桶
希望文章对你们有所帮助

自动补全的功能其实在很多平台都有,包括了对拼音内容进行补全,例如输入“sj”可能会弹出“手机”。
实现这种功能需要安装拼音分词器,同时我们需要对其进行自定义,然后开始在之前的旅游类项目中增加搜索框自动补全的功能。
同样的,先把DSL语句掌握,再根据DSL语句去写java代码,去做实战,就会很容易。

深入ElasticSearch(2)——自动补全

  • 安装拼音分词器
  • 自定义分词器
  • DSL实现自动补全查询
  • 修改酒店索引库数据结构
  • restAPI实现自动补全查询
  • 实现搜索框自动补全

安装拼音分词器

安装方式和之前安装IK分词器是一样的,解压完上传到虚拟机中elasticsearch的plugin目录,再重启elasticsearch。
拼音分词器的压缩包可以从百度网盘中下载:

链接:https://pan.baidu.com/s/1qEwp3StkW7IJuhow-yAunA?pwd=fc9r
提取码:fc9r

在这里插入图片描述
终端输入docker restart es即可。

在dev tools中测试一下:

POST /_analyze
{"text": ["如家酒店还不错"],"analyzer": "pinyin"
}

在这里插入图片描述

自定义分词器

现在的拼音分词器还没有办法应用到生产环境中,上图中拼音分词器中分出了“rjjdhbc”这样的结果,同时它们还对全部单独的字进行了拼音,说明它根本不会分词。
还有一个问题,这里的分词器分出了拼音,这在真实应用场景下是锦上添花,但是偏偏没有了汉字,这显然是不行的。

elasticsearch中分词器的组成包含三部分:

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

在这里插入图片描述
所以,既然拼音分词器本身不会分词,那就先把文本交给ik分词器,分词后再转换为拼音。
要想自定义分词器,可以在创建索引库时,通过setting来配置自定义的analyzer(分词器):

PUT /test
{"settings": {"analysis": {"analyzer": { # 自定义分词器"tokenizer": "ik_max_word","filter": "pinyin"}}}
}

虽然分好词了,但是拼音分词器对每个词,还是分成一个字一个字的来设置拼音,因此需要做进一步处理,即对拼音分词器进行自定义,不再使用默认的"pinyin":

PUT /test
{"settings": {"analysis": {"analyzer": {"my_analyzer": {"tokenizer": "ik_max_word","filter": "py"}},"filter": { # 自定义tokenizer 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}}}}
}

最终语句如下:
在这里插入图片描述
现在就可以进行测试,用自定义的分词器my_analyzer来做分词,注意需要指定索引库为/test,因为这个自定义分词器是在/test索引库下创建的,也只能在这里使用:

POST /test/_analyze
{"text": ["如家酒店还不错"],"analyzer": "my_analyzer"
}

但还是有一定的问题的,比如搜索狮子,结果中会包含虱子,也就是说把同音字都给搜进去了。
实际上,创建倒排索引时:
在这里插入图片描述
这时候再搜索的时候,就会因为拼音分词器的存在,shizi的词条对应了1和2的文档编号,就会产生混乱。

也就是说,拼音分词器适合在创建倒排索引的时候使用,但不能在搜索的时候使用。

因此,字段在创建倒排索引时应该用my_analyzer分词器,在搜索时应该用ik_smart分词器:

"mappings": {"properties": {"name": {"type": "text","analyzer": "my_analyzer","search_analyzer": "ik_smart"}}
}

在这里插入图片描述
总结:创建索引时用拼音分词器,搜索时用IK分词器。

DSL实现自动补全查询

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

参与补全查询的字段必须是completion类型。
字段的内容一般是用来补全的多个词条形成的数组。

在这里插入图片描述
这样做,输入S会弹出Sony,输入W会弹出WH…,把整个成语拆开显然更为人性化。

查询语法如下:

GET /test/_search
{"suggest": { # 自动补全"title_suggest": { # 自动补全这个操作的名称"text": "s", # 查询的前缀"completion": { # 自动补全的类型,使用完全补全"field": "title","skip_duplicates": true, # 跳过重复的"size": 10}}}
}

修改酒店索引库数据结构

接下来要实现hotel索引库的自动补全、拼音搜索功能。需要先将酒店的索引库数据结构修改,实现步骤:
1、修改hotel索引库结构,设置自定义拼音分词器
2、修改索引库的name、all字段,使用自定义分词器
3、索引库添加一个新字段suggestion,类型为completion,使用自定义的分词器

记得先删掉之前的hotel索引库,再创建实现上面3步:

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"}}}
}

4、给HotelDoc类添加suggestion字段,内容包括brand、business
在这里插入图片描述

5、重新导入数据到hotel库,之前已经编写了这个测试类了:
在这里插入图片描述
在这里插入图片描述

restAPI实现自动补全查询

在这里插入图片描述
编写测试类获取response并逐层解析结果:

	@Testvoid testSuggest() throws IOException {SearchRequest request = new SearchRequest("hotel");request.source().suggest(new SuggestBuilder().addSuggestion("suggestion",SuggestBuilders.completionSuggestion("suggestion").prefix("h").skipDuplicates(true).size(10)));SearchResponse response = client.search(request, RequestOptions.DEFAULT);Suggest suggest = response.getSuggest();CompletionSuggestion suggestion = suggest.getSuggestion("suggestion");for (CompletionSuggestion.Entry.Option option : suggestion.getOptions()) {String text = option.getText().toString();System.out.println("text = " + text);}}

在这里插入图片描述

实现搜索框自动补全

查看前端页面,可以发现在输入框输入的时候,前端就会发起Ajax请求:
在这里插入图片描述
在这里插入图片描述
既然已经携带了输入的参数,要实现自动补全,需要在服务端编写接口,接收该请求,返回补全结果的集合,类型为List<String>。

HotelController:

	@GetMapping("/suggestion")public List<String> getSuggestion(@RequestParam("key") String prefix) {return hotelService.getSuggestion(prefix);}

实现类HotelService:

	@Overridepublic List<String> getSuggestion(String prefix) {try {SearchRequest request = new SearchRequest("hotel");request.source().suggest(new SuggestBuilder().addSuggestion("suggestions",SuggestBuilders.completionSuggestion("suggestion").prefix(prefix).skipDuplicates(true).size(10)));SearchResponse response = client.search(request, RequestOptions.DEFAULT);//解析结果Suggest suggest = response.getSuggest();CompletionSuggestion suggestion = suggest.getSuggestion("suggestions");List<CompletionSuggestion.Entry.Option> options = suggestion.getOptions();List<String> 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);}}

在这里插入图片描述
在这里插入图片描述

至此,自动补全功能正式实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658458.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows断开映射磁盘提示“此网络连接不存在”,并且该磁盘直在资源管理器中

1、打开注册表编辑器 快捷键winR 打开“运行”&#xff0c; 输入 regedit 2、 删除下列注册表中和无法移除的磁盘相关的选项 \HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\ 3、打开“任务管理器”&#xff0c;重新启动“Windows资源…

java如何判断空值

1 前言 2 List的判空 3 String的判空 4 Optional 4.1 Optional对象的创建 4.2 使用场景 5 总结 1 前言 实际项目中我们会有很多地方需要判空校验&#xff0c;如果不做判空校验则可能产生NullPointerException异常。 针对异常的处理我们在上一篇有提及&#xff1a; 先来看一下…

网络安全运营专家的职业发展路径

网络安全运营分析师/专家是企业组织在网络威胁环境中建立强大防御能力的关键因素&#xff0c;承担着监控安全警报、分析潜在威胁以及响应突发性安全事件等职责。一名成功的网络安全运营分析师需要同时具备专业安全能力和软性职场技能&#xff0c;并且不断地学习提升&#xff0c…

Spring Boot第一天

SpringBoot概述 Spring Boot是Spring提供的一个子项目&#xff0c;用于快速构建Spring应用程序 传统方式构建Spring应用程序 导入依赖繁琐 项目配置繁琐 为了简化如此繁琐的配置流程&#xff0c;SpringBoot这一子项目提供了如下特性 SpringBoot特性 起步依赖 本质上就是一个…

代码随想录算法训练营第十六天 | 完全二叉树

目录 完全二叉树 LeetCode 222. 完全二叉树的节点个数 完全二叉树 作者&#xff1a;labuladong 如何求一棵完全二叉树的节点个数呢&#xff1f; // 输入一棵完全二叉树&#xff0c;返回节点总数 int countNodes(TreeNode root);如果是一个普通二叉树&#xff0c;显然只要向…

Camunda中强大的监听服务

文章目录 简介创建工程JavaDelegateTaskListenerExecutionListener部署发起流程CustomExecutionListener开始节点CustomExecutionListenerCustomJavaDelegateCustomExecutionListenerCustomTaskListener用户节点 ExpressionDelegate Expression流程图 简介 Camunda预览了很多接…

MTK8365安卓核心板_联发科MT8365(Genio 350)核心板规格参数

MTK8365安卓核心板是一款高性能的嵌入式处理器产品&#xff0c;基于联发科领先的SoC架构和先进的12纳米工艺。它集成了四核ARM Cortex-A53处理器&#xff0c;每个核心频率高达2.0 GHz&#xff0c;搭载强大的多标准视频加速器&#xff0c;支持高达1080p 60fps的视频解码。此外&a…

数据库(SQL)

目录 1 触发器 1.1 触发器简介 1.2 触发器的创建 语法 说明 1.3 示例 2 存储过程 2.1 什么是存储过程&#xff08;函数&#xff09; 2.1.1 存储过程和存储函数的区别 2.2 优势 2.3 应用场景 2.4 存储过程的创建和使用 说明 各参数类型所实现的存储过程 无参数无返…

[cmake]CMake Error: Could not create named generator Visual Studio 16 2019解决方法

配置flycv时&#xff0c;cmake以下代码会报错第二行的错误&#xff0c;网上解决方法为第三行代码 cmake .. -G "Visual Studio 16 2019 Win64" CMake Error: Could not create named generator Visual Studio 16 2019 cmake .. -G "Visual Studio 16 2019"…

【MBtiles数据格式说明】GeoServer改造Springboot番外系列一

一、MBTiles数据格式 MBTiles格式是指由MapBox制定的一种将瓦片地图数据存储到SQLite数据库中并可快速使用、管理和分享的规范&#xff0c;是一种用于即时使用和高效传输的规范。MBTiles既可以用作栅格输入数据存储&#xff0c;也可以用作WMSGetMap输出格式。规范有1.0&#xf…

C++类和对象:多态应用实例

利用多态实现计算机组转流程&#xff1a; polymorphic -> 多态 基础零件&#xff08;抽象类&#xff09;&#xff1a; class CPU { public:virtual void calculate() 0; }; class VideoCard { public:virtual void display() 0; }; class Memory { public:virtual void…

每日算法打卡:动态求连续区间和 day 31

文章目录 原题链接题目描述输入格式输出格式数据范围输入样例&#xff1a;输出样例&#xff1a; 题目分析示例代码树状数组线段树 原题链接 1264. 动态求连续区间和 题目难度&#xff1a;简单 题目来源&#xff1a;《信息学奥赛一本通》 题目描述 给定 n 个数组成的一个数…

rp-bf:一款Windows下辅助进行ROP gadgets搜索的Rust库

关于rp-bf rp-bf是一款Windows下辅助进行ROP gadgets搜索的Rust库&#xff0c;该工具可以通过模拟Windows用户模式下的崩溃转储来爆破枚举ROP gadgets。 在很多系统安全测试场景中&#xff0c;研究人员成功劫持控制流后&#xff0c;通常需要将堆栈数据转移到他们所能够控制的…

第一批 Apple Vision Pro 开箱和佩戴体验新鲜出炉!!!

注: 本文转自微信公众号 BravoAI (专注AI资讯和技术分享), 原文网址:第一批 Apple Vision Pro 开箱和佩戴体验新鲜出炉!!!, 扫码关注公众号 编者按: 整个AR/VR行业都在等AVP, 期待它能带来ChatGPT般的冲击 AVP(Apple Vision Pro) 是苹果公司研发的第一款"空间计算 (Spa…

VOD-SLAM 复现 AirDos 复现

VOD-SLAM 复现 参考&#xff1a;https://www.mianshigee.com/project/halajun-VDO_SLAM/ 下载&#xff1a; git clone https://github.com/halajun/VDO_SLAM.git VDO-SLAMCSparse 库安装 sudo apt-get install libsuitesparse-dev解决&#xff1a;fatal error: opencv2/xfea…

基础小白快速入门python------Python程序设计结构,循环

循环在计算机中&#xff0c;是一个非常重要的概念&#xff0c;是某一块儿代码的不断重复运行&#xff0c;是一种逻辑思维 在编程中的体现&#xff0c;运用数学思维加代码结合加数据&#xff0c;就构成了一个循环。 在Python中&#xff0c;循环主要分为三大类 for循环 while循…

Revit中使用依赖注入

依赖注入的技术已经很成熟&#xff0c;本文主要是说明一下Revit中的适用版本与介绍相关的开源项目。 版本问题 版本 目前的依赖注入包无法支持Revit 2020 以下的版本&#xff0c;原因是因为包中的依赖项与Revit本身的依赖项不一致导致的&#xff0c;所以说如果使用Revit DI…

力扣hot100 括号生成 递归回溯 超简洁版

Problem: 22. 括号生成 Code 使用 static 会被复用 class Solution {List<String> ans new ArrayList<>();public List<String> generateParenthesis(int n){dfs(n, n, "");return ans;}/*** param l 左括号待补个数* param r 右括号待补个数*…

nodejs+vue+ElementUi电商购物个性化商城推荐系统gqfe

电本电商个性化推荐系统是为了提高用户查阅信息的效率和管理人员管理信息的工作效率&#xff0c;可以快速存储大量数据&#xff0c;还有信息检索功能&#xff0c;这大大的满足了用户和管理员这二者的需求。操作简单易懂&#xff0c;合理分析各个模块的功能&#xff0c;尽可能优…

ansible 常用命令 基本说明 个人备忘

linux下设置一台机器的名称为ansible hostnamectl set-hostname ansible //设置一台机器的名称为master-01 hostnamectl set-hostname master-01 hostnamectl set-hostname master-02 hostnamectl set-hostname node01 hostnamectl set-hostname node02 hostnamectl set-…