ElasticSearch学习笔记(六)自动补全、拼音分词器、RabbitMQ实现数据同步

文章目录

  • 前言
  • 11 自动补全
    • 11.1 拼音分词器
    • 11.2 自定义分词器
    • 11.3 自动补全查询
  • 12 数据同步
    • 12.1 实现方案
      • 12.1.1 同步调用
      • 12.1.2 异步通知
      • 12.1.3 监听binlog
    • 12.2 异步通知实现数据同步
      • 12.2.1 声明交换机和队列
      • 12.2.2 发送MQ消息
      • 12.2.3 接收MQ消息并操作ES

前言

ElasticSearch学习笔记(一)倒排索引、ES和Kibana安装、索引操作
ElasticSearch学习笔记(二)文档操作、RestHighLevelClient的使用
ElasticSearch学习笔记(三)RestClient操作文档、DSL查询文档、搜索结果排序
ElasticSearch学习笔记(四)分页、高亮、RestClient查询文档
ElasticSearch学习笔记(五)Bucket聚合、Metric聚合

11 自动补全

在搜索页面,当用户在搜索框输入字符时,应该提示出与该字符有关的搜索项。例如:

这种根据用户输入的字母,提示完整词条的功能,就是自动补全。由于需要根据拼音字母来推断,因此要用到拼音分词功能。

11.1 拼音分词器

要实现根据拼音字母做自动补全,就必须对文档按照拼音分词。

在GitHub上下载elasticsearch的拼音分词插件,地址:https://github.com/medcl/elasticsearch-analysis-pinyin

  • 1)将下载的elasticsearch-analysis-pinyin-7.12.1.zip上传到服务器并解压

  • 2)将插件移动到ES的插件目录/var/lib/docker/volumes/es-plugins/_data/

  • 3)重启ES

  • 4)功能测试

11.2 自定义分词器

默认的拼音分词器会将每个汉字单独分为拼音,但仍然不能满足需求,我们希望的是每个词条形成一组拼音。为此需要对拼音分词器做个性化定制,形成自定义分词器。

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

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

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

PUT /test
{"settings": {"analysis": {"analyzer": {"my_analyzer": { // 自定义分词器名称"tokenizer": "ik_max_word", // 词条切割规则"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": {"name": {"type": "text","analyzer": "my_analyzer","search_analyzer": "ik_smart"}}}
}

功能测试:

11.3 自动补全查询

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

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

例如,把酒店的品牌、城市、商圈等信息放入一个completion类型的字段中,作为自动补全的提示。

  • 1)由于已经创建好的索引库是无法修改的,因此要删除然后重新创建
DELETE /hotel
  • 2)修改索引库结构,主要做如下改动:设置自定义拼音分词器;修改nameall字段,使用自定义分词器;添加一个新字段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,类型为completion类型"suggestion":{"type": "completion","analyzer": "completion_analyzer"}}}
}

  • 3)给HotelDoc类添加suggestion字段,内容包含brandbusinesscity
public class HotelDoc {// ......private String brand;private String city;private String business;private List<String> S;public HotelDoc(Hotel hotel) {// ......this.brand = hotel.getBrand();this.city = hotel.getCity();this.business = hotel.getBusiness();// 组装suggestionif(this.business.contains("/")){// business有多个值,需要切割String[] arr = this.business.split("/");// 添加元素this.suggestion = new ArrayList<>();this.suggestion.add(this.brand);this.suggestion.add(this.city);Collections.addAll(this.suggestion, arr);} else {this.suggestion = Arrays.asList(this.brand, this.business, this.city);}}
}
  • 4)重新导入数据到hotel索引库

  • 5)DSL实现自动补全查询
GET /hotel/_search
{"suggest": {"mySuggestion": { // 自定义名字"text": "sh", // 关键字"completion": {"field": "suggestion", // 要补全的字段"skip_duplicates": true, // 跳过重复项"size": 10 // 查询10条数据}}}
}

  • 5)RestAPI实现自动补全查询
@Test
public void testSuggestion() throws IOException {// 1.创建Request对象SearchRequest request = new SearchRequest("hotel");// 2.准备参数request.source().suggest(new SuggestBuilder().addSuggestion("mySuggestion", // 自定义名字SuggestBuilders.completionSuggestion("suggestion") // 要补全的字段.prefix("sh") // 关键字.skipDuplicates(true) // 跳过重复项.size(10)) // 查询10条数据);// 3.发送请求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.处理结果Suggest suggest = response.getSuggest();// 根据名称获取补全结果CompletionSuggestion mySuggestion = suggest.getSuggestion("mySuggestion");// 获取options并遍历for (CompletionSuggestion.Entry.Option option : mySuggestion.getOptions()) {// 获取option中的textString text = option.getText().string();System.out.println(text);}
}

执行以上单元测试,得到如下结果:

12 数据同步

ES中的酒店数据来源于MySQL数据库,因此MySQL数据发生改变时,ES也必须跟着改变,这个就是ES与MySQL之间的数据同步。

12.1 实现方案

12.1.1 同步调用

如上图所示,hotel-demo酒店搜索服务对外提供了一个接口。hotel-admin酒店管理服务在完成数据库操作后,直接调用hotel-demo提供的接口,修改ES中的数据。这种方式实现简单,但业务耦合度较高。

12.1.2 异步通知

如上图所示,hotel-admin酒店管理服务在完成数据库操作后,发送对应的MQ消息到队列。hotel-demo酒店搜索服务监听MQ,接收到消息后完成ES数据修改。这种方式实现难度一般,且低耦合,但对MQ的可靠性依赖较高。

12.1.3 监听binlog

如上图所示,MySQL开启了binlog功能,hotel-admin酒店管理服务完成增、删、改操作都会记录在binlog中
。hotel-demo酒店搜索服务基于canal监听binlog变化,实时更新ES中的内容。这种方式完全解除服务间耦合,但开启binlog会增加数据库负担,且实现复杂度高。

12.2 异步通知实现数据同步

12.2.1 声明交换机和队列

使用docker安装rabbitmq的方法参考:RabbitMQ学习笔记(一)RabbitMQ部署、5种队列模型

  • 1)引入依赖
<!--amqp-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • 2)声明交换机和队列的名称
public class MqConstants {/*** 交换机名称*/public final static String HOTEL_EXCHANGE = "hotel.topic";/*** 新增和修改的队列名称*/public final static String HOTEL_INSERT_QUEUE = "hotel.insert.queue";/*** 删除的队列名称*/public final static String HOTEL_DELETE_QUEUE = "hotel.delete.queue";/*** 新增或修改的RoutingKey*/public final static String HOTEL_INSERT_KEY = "hotel.insert";/*** 删除的RoutingKey*/public final static String HOTEL_DELETE_KEY = "hotel.delete";
}
  • 3)声明交换机和队列
package com.star.sc.totel.mq;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MqConfig {@Beanpublic TopicExchange topicExchange(){return new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false);}@Beanpublic Queue insertQueue(){return new Queue(MqConstants.HOTEL_INSERT_QUEUE, true);}@Beanpublic Queue deleteQueue(){return new Queue(MqConstants.HOTEL_DELETE_QUEUE, true);}@Beanpublic Binding insertQueueBinding(){return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);}@Beanpublic Binding deleteQueueBinding(){return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);}
}

12.2.2 发送MQ消息

@Autowired
private RabbitTemplate rabbitTemplate;@Test
public void testSaveHotel() {Hotel hotel = new Hotel();hotel.setId(2359697L);rabbitTemplate.convertAndSend(MqConstants.HOTEL_EXCHANGE, MqConstants.HOTEL_INSERT_KEY, hotel.getId());
}

执行以上单元测试,向rabbitmq发送消息,在管理页面可以看到这条消息:

12.2.3 接收MQ消息并操作ES

package com.star.sc.totel.mq;import com.alibaba.fastjson.JSON;
import com.star.sc.totel.pojo.Hotel;
import com.star.sc.totel.pojo.HotelDoc;
import com.star.sc.totel.service.IHotelService;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class HotelListener {@Autowiredprivate RestHighLevelClient client;@Autowiredprivate IHotelService hotelService;/*** 监听酒店新增或修改的业务* @param id 酒店id*/@RabbitListener(queues = MqConstants.HOTEL_INSERT_QUEUE)public void listenHotelInsertOrUpdate(Long id) throws IOException {System.out.println("监听到酒店新增或修改的业务,id=" + id);// 1.根据id查询酒店数据Hotel hotel = hotelService.getById(id);HotelDoc hotelDoc = new HotelDoc(hotel);// 2.发送请求IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);client.index(request, RequestOptions.DEFAULT);}/*** 监听酒店删除的业务* @param id 酒店id*/@RabbitListener(queues = MqConstants.HOTEL_DELETE_QUEUE)public void listenHotelDelete(Long id){System.out.println("监听到酒店删除的业务,id=" + id);}}

启动该监听器,日志显示读取到了MQ消息:

本节完,更多内容请查阅分类专栏:微服务学习笔记

感兴趣的读者还可以查阅我的另外几个专栏:

  • SpringBoot源码解读与原理分析
  • MyBatis3源码深度解析
  • Redis从入门到精通
  • MyBatisPlus详解
  • SpringCloud学习笔记

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

互联网职场说 | “400w能否实现‘躺平’的生活”

近年来&#xff0c;“躺平”一词在国内职场中频频出现&#xff0c;表达了许多年轻人对工作压力和生活负担的不满与逃避心理。 近日&#xff0c;一位网友在社交平台上提出了一个引人深思的问题&#xff1a;“400万可以躺平吗&#xff1f;有房有车无贷款。” 网友们也各抒己见&a…

GB/T28181规范和JT1078交通部标差异

技术背景 好多开发者区分不太清楚GB/T28181和JT1078规范&#xff0c;实际上&#xff0c;二者在规范定义、技术特点、过检认证以及应用场景等方面均存在显著差异。两者各有其适用领域和优势&#xff0c;但在某些特定场景下也可能需要相互协作以实现更全面的监控和管理。 规范定…

[学术论文] KBS期刊介绍及投稿流程学习笔记

该专栏主要是论文投稿的记录笔记&#xff0c;希望对初学者有所帮助&#xff0c;也希望大家论文都能命中。这篇文章主要介绍人工智能一区期刊Knowledge-Based Systems的投稿笔记&#xff0c;希望您喜欢&#xff01; 文章目录 一.期刊介绍二.投稿地址及模板1.投稿地址2.LaTex下载…

[工具使用]git

git fetch 获取远程仓库内容&#xff0c;但未合入本地仓库&#xff1b; git rebase 获取远程仓库内容&#xff0c;并更改基地合入本地仓库&#xff1b; 将master分支的内容合入feature分支&#xff1a; 当在feature分支上执行git rebase master时&#xff0c;git会从master…

Datawhale X 李宏毅苹果书 AI夏令营-深度学习进阶task3:批量归一化

1.批量归一化 如果误差表面很崎岖&#xff0c;它比较难训练。批量归一化&#xff08;Batch Normalization&#xff0c;BN&#xff09;就是其中一个“把山铲平”的想法 如图 所示&#xff0c;假设两个参数对损失的斜率差别非常大&#xff0c;在 w1 这个方向上面&#xff0c;斜…

聚观早报 | 苹果推出AI消除功能;比亚迪2024上半年营收

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 8月30日消息 苹果推出AI消除功能 比亚迪2024上半年营收 真我GT7 Pro渲染图曝光 苹果iPhone 16开始印度量产 故宫…

旗帜分田(华为od机考题)

一、题目 1.原题 从前有个村庄&#xff0c;村民们喜欢在各种田地上插上小旗子&#xff0c;旗子上标识了各种不同的数字。 某天集体村民决定将覆盖相同数字的最小矩阵形的土地的分配给为村里做出巨大贡献的村民&#xff0c; 请问&#xff0c;此次分配土地&#xff0c;做出贡献…

MMsegmentation与MMdeploy简单使用

最近涉及到了图像分割的任务&#xff0c;于是拿来写下博客加深下使用。 MMsegmentation与MMdeploy的环境配置暂不做讲解&#xff0c;在官网和其他博客中有很多说明。 MMdeploy主要是把pt转为 onnx_int8的情况。 MMsegmentation环境配置可以参考 : 安装与配置MMSegmentation 目录…

DriveLM的baseline复现

DriveLM是一篇很有意思的工作&#xff0c;把自动驾驶跟MLLM结合到一起了&#xff0c;实现端到端的决策。 Repo&#xff1a;https://github.com/OpenDriveLab/DriveLM 该工作是基于nuScenes数据集做的&#xff0c;官方paper里给出了数据的具体构建方式&#xff0c;感兴趣的可以…

[HZNUCTF 2023 preliminary]easyAPK-快坚持不下去的第三天

第一做安卓题&#xff0c;前提jadx,java环境&#xff0c;模拟器&#xff0c;我配了好久&#xff0c; 这段代码实现了一个简单的登录界面&#xff0c;用户需要输入用户名和密码。用户名和密码会与预设的硬编码值进行比较&#xff0c;登录成功后会启动另一个 Activity。如果密码错…

★ 算法OJ题 ★ 力扣11 - 盛水最多的容器

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将和大家一起做一道双指针算法题--盛水最多的容器~ 目录 一 题目 二 算法解析 三 编写算法 一 题目 11. 盛最多水的容器 - 力扣&#xff08;LeetCode&#xff09; 二 算法解析 解法1&#xff1a;暴力枚举 …

Mysql基础练习题 620.有趣的电影 (力扣)

620.编写解决方案&#xff0c;找出所有影片描述为 非 boring (不无聊) 的并且 id 为奇数 的影片,返回结果按 rating 降序排列 题目链接&#xff1a; https://leetcode.cn/problems/not-boring-movies/ 建表插入数据&#xff1a; Create table If Not Exists cinema (id int…

【云原生系列之SkyWalking的部署】

1、分布式链路追踪 1.1概念 在较大的web集群和微服务环境中&#xff0c;客户端的一次请求需要经过不同的模块&#xff0c;多个不同中间件&#xff0c;多个不同机器一起相互协作才能处理完成客户端的请求&#xff0c;而在这一系列的请求过程之中,处理流程可能是串行执行,也可能…

论斜率优化dp

论斜率优化dp 1问题2暴力算法-线性dp3斜率优化线性dp4后记 1问题 如下图 看到这题&#xff0c;题面很复杂 其实可以转化为如下问题 有 n n n个任务&#xff0c;排成一个有序序列&#xff0c;我们要解决这些任务 总费用是每一个任务的完成时间乘以费用系数求和 每个任务之前…

sessionstorage和localstorage的使用与区别

sessionstorage和localstorage的使用与区别 localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。他们均只能存储字符串类型的对象&#xff08;虽然规范中可以存储其他原生类型的对象&#xff0c;但是目前为止没有浏览器对其进行实现&#xff09;。 localStor…

Hadoop 下载

下载法一&#xff1a;官方下载 hadoop官网 1.选择要下载的版本&#xff0c;这里我以3.4.0为例进行说明&#xff1b; 2.跳转后&#xff0c;选择对应系统架构的&#xff0c;进行下载&#xff1b; 下载法二&#xff1a;国内镜像源下载 1.阿里云 这里我以mac m1为案例&#x…

Linux日志-wtmp日志

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux 系统中的日志是记录系统活动和事件的重要工具&#xff0c;它们可以帮助管理员监视系统状态、调查问题以及了解系统运行…

【保姆级教程】如何在Win11上搭建一个GPU环境

CUDA和CUDNN安装 CUDA安装 下载对应cuda环境 下载链接&#xff1a;https://developer.nvidia.com/cuda-downloads&#xff0c;图片下载的是 cuda_12.6.1_560.94_windows.exe 然后一路安装即可&#xff1a; 安装路径如下&#xff1a; CUDNN安装 打开cuDNN下载页面 解压后…

嵌入式基础知识-RS232通信协议电路与代码最全分析

1.RS232基本概念 RS232是异步通信&#xff0c;全双工传输&#xff08;异步通信就是无时钟CLK信号&#xff0c;全双工就是能同时收发数据&#xff09;。采用负逻辑传送&#xff0c;规定逻辑“1”的电平为-5V~-15 V&#xff0c;逻辑“0”的电平为5 V&#xff5e;15 V。选用该电气…

阻塞队列-单锁实现

使用阻塞队列 当我们多个线程下 对 一个队列进行操作&#xff0c;队列满了的情况下&#xff0c;其他线程再次 offer&#xff0c;会一直阻塞等待 对一个队列进行出队操作的时候&#xff0c;队列空的情况下&#xff0c;会一直阻塞等待删除&#xff0c;直到队列有元素的时候&a…