使用ElasticSearch实现全文检索
文章目录
- 全文检索
- 任务描述
- 技术难点
- 任务目标
- 实现过程
- 1. java读取Json文件,并导入MySQL数据库中
- 2. 利用Logstah完成MySQL到ES的数据同步
- 3. 开始编写功能接口
- 3.1 全文检索接口
- 3.2 查询详情
- 4. 前端调用
全文检索
任务描述
- 在获取到数据之后如何在ES中进行数据建模,以方便之后搜索接口的实现
- 接下来,要考虑的问题是,如何实现MySQL和ES的数据同步
- 接下来是技术实现,要如何实现基于关键词进行全文检索和对于某一条数据的查询详情
- 在接口实现之后,前端调用后端暴露的接口来进行数据获取,并在页面进行展示
技术难点
- 数据同步
- ES的检索的实现
- 精确定位MySQL表中的数据
任务目标
- 根据关键词进行全文检索
- 查询详情
实现过程
1. java读取Json文件,并导入MySQL数据库中
public List<Workticket> getWorkticket(){ObjectMapper objectMapper = new ObjectMapper();List<Workticket> jsonObjects = null;try {jsonObjects = objectMapper.readValue(new File("D:\\data_hanchuan\\workticket.json"), List.class);} catch (IOException e) {e.printStackTrace();}return jsonObjects;}
上述代码将json文件的数据封装成对象,然后调用MP的批量增加方法(deviceService.saveBatch(list);),将其添加到hanchuan数据库中
2. 利用Logstah完成MySQL到ES的数据同步
【注】Logstash、ES以及Kibana必须版本一致
主要参考logstash这篇博客,完成从MySQL到ES的数据同步。下面是其中的一张表的 .conf文件(几张表就对应几个conf文件)
input {stdin {}jdbc {type => "jdbc"# 数据库连接地址jdbc_connection_string => "jdbc:mysql://localhost:3306/hanchuan?characterEncoding=UTF-8&autoReconnect=true&allowPublicKeyRetrieval=true"# 数据库连接账号密码;jdbc_user => "root"jdbc_password => "root"# MySQL依赖包路径;jdbc_driver_library => "D:\apply_soft\elasticsearch_all_soft\logstash-7.6.1\bin\result\mysql-connector-j-8.0.31.jar"# the name of the driver class for mysqljdbc_driver_class => "com.mysql.jdbc.Driver"# 数据库重连尝试次数connection_retry_attempts => "3"# 判断数据库连接是否可用,默认false不开启jdbc_validate_connection => "true"# 数据库连接可用校验超时时间,默认3600Sjdbc_validation_timeout => "3600"# 开启分页查询(默认false不开启);jdbc_paging_enabled => "true"# 单次分页查询条数(默认100000,若字段较多且更新频率较高,建议调低此值);jdbc_page_size => "3000"# statement为查询数据sql,如果sql较复杂,建议配通过statement_filepath配置sql文件的存放路径;# sql_last_value为内置的变量,存放上次查询结果中最后一条数据tracking_column的值,此处即为ModifyTime;# statement_filepath => "mysql/jdbc.sql"statement => "SELECT id,defective_appearance,leakage_type,anbiao1,subsystem,duty_group,anbiao2,defective_why,elimination_person,department,accept_describe,accept_group from defect where id > :sql_last_value order by id desc"# 是否将字段名转换为小写,默认true(如果有数据序列化、反序列化需求,建议改为false);lowercase_column_names => false# Value can be any of: fatal,error,warn,info,debug,默认info;sql_log_level => warn## 是否记录上次执行结果,true表示会将上次执行结果的tracking_column字段的值保存到last_run_metadata_path指定的文件中;record_last_run => true# 需要记录查询结果某字段的值时,此字段为true,否则默认tracking_column为timestamp的值;use_column_value => true# 需要记录的字段,用于增量同步,需是数据库字段tracking_column => "id"# record_last_run上次数据存放位置;last_run_metadata_path => "result/defect/last_id.txt"# 是否清除last_run_metadata_path的记录,需要增量同步时此字段必须为false;clean_run => false## 同步频率(分 时 天 月 年),默认每分钟同步一次;schedule => "* * * * *"}
}filter {mutate { //挑选其中的一个字段充当title字段rename => {"defective_appearance" => "title"} //将其id值设置为”数据库表名001_id“ 方便之后查询详情接口的实现update => {"id" => "defect001_%{id}"}// 将其他字段填充到message字段当中add_field => {"message" =>["%{title};%{leakage_type};%{anbiao1};%{subsystem};%{duty_group};%{anbiao2};%{defective_why};%{elimination_person};%{department};%{accept_describe};%{accept_group};"]}//将多余字段删除,使表的结构始终呈现为{id,title,message}形式remove_field => ["leakage_type","anbiao1","subsystem","duty_group","anbiao2","defective_why","elimination_person","department","accept_describe","accept_group"]}}output {elasticsearch {# host => "192.168.1.1"# port => "9200"# 配置ES集群地址hosts => ["localhost:9200"]# 索引名字,必须小写index => "hanchuan001"}stdout {codec => json_lines}
}
最终我们ES中的数据结构就是下面这个样子

3. 开始编写功能接口
3.1 全文检索接口
@Overridepublic MetaTotal searchAllHighLight(String msg, int pageNo, int pageSize) throws IOException {if (pageNo <= 1) {pageNo = 1;}SearchRequest request = new SearchRequest(resultIndex);
// 进行搜索SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();boolQueryBuilder.must(QueryBuilders.matchQuery("message", msg)).should(QueryBuilders.matchQuery("title", msg));// sourceBuilder.size(2000);// 分页sourceBuilder.from(pageNo);sourceBuilder.size(pageSize);// 进行高亮设置HighlightBuilder highlightBuilder = new HighlightBuilder();HighlightBuilder.Field field = new HighlightBuilder.Field("message").preTags("<span style='color:red'>").postTags("</span>");HighlightBuilder.Field field1 = new HighlightBuilder.Field("title").preTags("<span style='color:red'>").postTags("</span>");highlightBuilder.field(field).field(field1);sourceBuilder.query(boolQueryBuilder);sourceBuilder.highlighter(highlightBuilder);// 加入到request中request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);List<Meta> list = new ArrayList<>();for (SearchHit hit : response.getHits().getHits()) {//----进行高亮字段的替换Map<String, HighlightField> highlightFields = hit.getHighlightFields();HighlightField message = highlightFields.get("message");HighlightField title = highlightFields.get("title");// 未高亮之前的结果Map<String, Object> sourceAsMap = hit.getSourceAsMap();
// 1.找到message中出现关键字的地方进行高亮替换if (message != null) {Text[] fragments = message.fragments();String n_mess = "";for (Text text : fragments) {n_mess += text;}sourceAsMap.put("message", n_mess);}
// 2.找到title中出现关键字的地方进行高亮替换if (title != null) {Text[] fragments = title.fragments();String n_title = "";for (Text text : fragments) {n_title += text;}sourceAsMap.put("title", n_title);}//----结束----Meta meta = new Meta();try {BeanUtils.populate(meta, hit.getSourceAsMap());} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}list.add(meta);}MetaTotal metas = new MetaTotal();metas.setList(list);metas.setTotal(response.getHits().getTotalHits().value);System.out.println(metas.getTotal() + "总记录数");return metas;}
在业务逻辑代码写好之后在控制层暴露接口
@ResponseBody@GetMapping("/search/{keyword}/{pageNo}/{pageSize}")public Result searchByMsg(@PathVariable String keyword,@PathVariable int pageNo,@PathVariable int pageSize) throws IOException {MetaTotal metas = service.searchAllHighLight(keyword,pageNo,pageSize);Page<Meta> page = new Page<>(pageNo,pageSize);page.setRecords(metas.getList());page.setTotal(metas.getTotal());return new Result().code(200).message("查询成功").data("list",metas.getList()).data("total",metas.getTotal());}
3.2 查询详情
根据前端传递的id值,进行解析,找到对应的数据库表,进行详情查看。
@RequestMapping("/details/{id}")@ResponseBodypublic Result look_details2(@PathVariable("id") String id, Map<String,Object> map){String[] str = id.split("001_");if (str[0].equals("defect")){Defect defect = defectService.getById(str[1]);return new Result().code(200).message("详情结果").data("details",defect);} else if (str[0].equals("device")) {Device device = deviceService.getById(str[1]);return new Result().code(200).message("详情结果").data("details",device);} else if (str[0].equals("riskcontroller")) {Riskcontroller riskcontroller = riskControllerService.getById(str[1]);return new Result().code(200).message("详情结果").data("details",riskcontroller);}else if (str[0].equals("security")) {Security security = securityService.getById(str[1]);return new Result().code(200).message("详情结果").data("details",security);}else if (str[0].equals("workticket")) {Workticket workticket = workticketService.getById(str[1]);return new Result().code(200).message("详情结果").data("details",workticket);}return new Result().code(500).message("查询失败");}
4. 前端调用


相关文章:
使用ElasticSearch实现全文检索
文章目录 全文检索任务描述技术难点任务目标实现过程1. java读取Json文件,并导入MySQL数据库中2. 利用Logstah完成MySQL到ES的数据同步3. 开始编写功能接口3.1 全文检索接口3.2 查询详情 4. 前端调用 全文检索 任务描述 在获取到数据之后如何在ES中进行数据建模&a…...
通过k-means对相似度较高的语句进行分类
本文介绍了如何使用K-Means算法对相似度较高的语句进行分类,并附上java案例代码 import java.util.ArrayList; import java.util.List; import java.util.Random;public class KMeansTextClustering {public static void main(String[] args) {// 初始化语句数据集…...
国信华源科技赋能长江蓄滞洪区水闸管护项目验收成果报道
“碧水悠悠绕古城,闸启长江万象新。”近日,由北京国信华源科技有限公司倾力打造的万里长江蓄滞洪区水闸管护项目,圆满通过验收,为这片鱼米之乡的防洪安全注入了新的科技活力。 长江之畔,水闸挺立,犹如干堤上…...
HTML:表格重点
用表格就用table caption为该表上部信息,用来说明表的作用 thead为表头主要信息,效果加粗 tbody为表格中的主体内容 tr是 table row 表格的行 td是table data th是table heading表格标题 ,一般表格第一行的数据都是table heading...
wine的使用方法
wine版本 所有分支,新的主要版本: wine-x.0 All branches, release candidates:各分支、候选版本: wine-x.0-rcn Stable branch updates: 稳定分支更新: wine-x.0.z Development branch updates: wine-x.y wine *.exe “更改目…...
Linux服务器离线安装unzip包
Linux服务器离线安装unzip包 1. 安装unzip包的目的 解压Docker部署包和服务部署包。 2. 查看当前环境是否已经安装unzip rpm -qa | grep --color unzip3. 下载对应的离线包 地址:http://www.rpmfind.net/linux/rpm2html/search.php?query&submitSearch 例…...
Excel拆分脚本
Excel拆分 工作表按行拆分为工作薄 工作表按行拆分为工作薄 打开要拆分的Excel文件,使用快捷键(AltF11)打开脚本界面,选择要拆分的sheet,打开Module,在Module中输入脚本代码,然后运行脚本 Su…...
Mybatis---事务
目录 引入 一、事务存在的意义 1.事务是什么? 2.Mybatis关于事务的管理 程序员自己控制处理的提交和回滚 引入 一、事务存在的意义 1.事务是什么? 多个操作同时进行,那么同时成功,那么同时失败。这就是事务。 事务有四个特性…...
企业直播间媒体分发新闻转播拉流推广名单(金融财经科技类)
【本篇由 言同数字媒体直播分发 原创】随着直播与短视频成为各大企业营销的重要手段,如何选择合适的视频平台进行内容分发与拉流成为了企业关注的焦点。对于财经和科技类企业而言,选择具有专业受众群体和广泛传播能力的平台尤为重要。下面是一些可以帮助…...
华为FreeBuds Pro 4丢了如何找回?(附查找功能使用方法)
华为FreeBuds Pro 4查找到底怎么用?华为FreeBuds Pro 4有星闪精确查找和离线查找,离线查找功能涵盖播放铃声、导航定位、星闪精确查找、上线通知、丢失模式、遗落提醒等。星闪精确查找是离线查找的子功能,当前仅华为FreeBuds Pro 4充电盒支持…...
若依微服务登录密码加密传输解决方案
文章目录 一、需求提出二、应用场景三、解决思路四、注意事项五、完整代码第一步:前端对密码进行加密第二步:后端工具类实现 RSA 加解密功能第三步:登录接口中添加解密逻辑 六、运行结果总结 一、需求提出 在默认情况下,RuoYi 微…...
NVR小程序接入平台/设备EasyNVR深度解析H.265与H.264编码视频接入的区别
随着科技的飞速发展和社会的不断进步,视频压缩编码技术已经成为视频传输和存储中不可或缺的一部分。在众多编码标准中,H.265和H.264是最为重要的两种。今天我们来将深入分析H.265与H.264编码的区别。 一、H.265与H.264编码的区别 1、比特率与分辨率 H.…...
Redisson常用方法
Redisson 参考: 原文链接 定义:Redisson 是一个用于与 Redis 进行交互的 Java 客户端库 优点:很多 1. 入门 1.1 安装 <!--redission--> <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifa…...
html自带的input年月日(date) /时间(datetime-local)/星期(week)/月份(month)/时间(time)控件
年月日期控件 type"date" <input type"date" id"StartDate" valueDateTime.Now.ToString("yyyy-MM-dd") /> //设置值 $("#StartDate").val("2024-12-12"); //获取值 var StartDate$("#StartDate&quo…...
CSS系列(12)-- 响应式设计详解
前端技术探索系列:CSS 响应式设计详解 📱 致读者:掌握响应式设计的艺术 👋 前端开发者们, 今天我们将深入探讨 CSS 响应式设计,学习如何创建适应各种设备的网页布局。 响应式基础 🚀 视口设…...
filecoin boost GraphQL API 查询
查询示例 查询失败交易 curl -X POST \ -H "Content-Type: application/json" \ -d {"query":"query { deals(limit: 10, query: \"failed to get size of imported\") { deals { ID CreatedAt Message } } }"} \ http://localhost:…...
SAS - Subtractive Port
在SAS(串行连接SCSI,Serial Attached SCSI)协议中,subtractive port 是一种特殊类型的端口,主要用于设备间的路由功能。它的作用是在路径选择过程中充当默认路径,以处理未明确指定路径的请求。以下是它的定…...
TCP客户端模拟链接websocket服务端
因一些特殊原因研究了下TCP模拟链接websocket。原理上可以连接但具体怎么连接怎么操作就不知道了,需要研究下,以下是个人研究的方案。 用线上和本地地址来做例子: 线上wss地址:wss://server.cs.com/cs/vido/1 本地地址ws://127…...
TypeScript 的崛起:全面解析与深度洞察
一、背景与起源 (一)JavaScript 的局限性 类型系统缺失 难以在编码阶段发现类型相关错误,导致运行时错误频发。例如,将字符串误当作数字进行数学运算,可能在运行时才暴露问题。函数参数类型不明确,容易传入…...
c#笔记2024
Ctrl r e自动添加get和set CompositeCurve3d 复合曲线 List<Entity> entS listline.Cast<Entity>().ToList();//list类型强转 前面拼上\u0003,就可以实现,不管有没有命令都能打断当前命令的效果 取消其他命令:Z.doc.SendStri…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
