详解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资源…

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…

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

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

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…

基础小白快速入门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-…

flutter 设置图片与文字的基线对齐

如题&#xff1a;如何实现图片和文字的基线对齐 众所周知&#xff0c;文字含有上下填充&#xff0c;这个填充是框架所给予的。 背景 在开发中&#xff0c;我当时遇到比较简单的布局&#xff0c;首先是左边图标右边文字&#xff0c;如下图所示&#xff0c; 很自然的就想到用R…

linux 使用命令创建mysql账户

目录 前言创建步骤 前言 mysql默认有一个root用户&#xff0c;这个账户权限太大了&#xff0c;用起来不太安全&#xff0c;我们通常是重新那家一个账户用于一般的数据库操作&#xff0c;下面介绍如何通过命令创建一个mysql账户。 创建步骤 登录mysql mysql -u root -p输入roo…

Unity3D正则表达式的使用

系列文章目录 unity工具 文章目录 系列文章目录前言一、匹配正整数的使用方法1-1、代码如下1-2、结果如下 二、匹配大写字母2-1、代码如下1-2、结果如下 三、Regex类3-1、Match&#xff08;&#xff09;3-2、Matches()3-3、IsMatch&#xff08;&#xff09; 四、定义正则表达式…

非内积级联学习

1.首页推荐非内积召回现状 非内积召回源是目前首页推荐最重要的召回源之一。同时非内积相比于向量化召回最终仅将user和item匹配程度表征为embeding内积&#xff0c;非内积召回仅保留item embedding&#xff0c;不构造user显式表征&#xff0c;而是通过一个打分网络计算用户-商…

Log4j2-24-log4j2 相同的日志打印 2 次

现象 相同的日志打印了两次&#xff0c;且因为日志的配置不同&#xff0c;导致脱敏的情况不一致。 代码与配置 代码 package com.ryo.log4j2.cfg.additivity;import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;public class SimpleDemo…

12.MySql服务

目录 1. 什么是数据库 1.1. 数据&#xff1a; 1.2. 数据库&#xff1a; 2. mysql概述 3. 版本及下载 4. yum仓库安装 4.1. 添加yum源 4.2. 安装 5. 本地RPM包安装 5.1. 使用迅雷下载集合包 5.2. 上传数据 5.3. 安装 6. 生产环境中使用通用二进制包安装 6.1. 作用…

十一、常用API——练习

常用API——练习 练习1 键盘录入&#xff1a;练习2 算法水题&#xff1a;练习3 算法水题&#xff1a;练习4 算法水题&#xff1a;练习5 算法水题&#xff1a; 练习1 键盘录入&#xff1a; 键盘录入一些1~100之间的整数&#xff0c;并添加到集合中。 直到集合中所有数据和超过2…