ES分词搜索
ES的使用
- 前言
- 作者使用的版本
- 作者需求
- 简介
- ES简略介绍
- ik分词器简介
- 使用
- es的直接简单使用
- es的查询
- es在java中使用
- 备注说明
前言
作者使用的版本
- es: 7.17.27
- spring-boot-starter-data-elasticsearch: 7.14.2
作者需求
作者接到一个业务需求,我们系统有份数据被用来查询,进行搜索改造。我们的数据是可以分为两层,第一层是物品,物品含有物品名和物品别名。第二层是规格型号,一个物品可以配置多个规格型号,同一物品不同规格型号有不同的价格。
原先的搜索只支持对物品名或别名的模糊搜索。将带出该物品下所有的规格列表被用来选择。比如说原来数据库里有个物品叫做 蒙古大马
,如果使用蒙古的大马
进行搜索时搜索不到的,需要对这种搜索进行支持。
于是,作者选用了es作为文本搜索。作者只达到了可用的效果,并没有深究es的文档。底部会放置文档链接。
如上所述,本文并不对es做详细介绍。在上面说明中,作者已经碰到了问题,而es可以解决这个问题,所以本文只大概讲述es为什么能够解决我的问题
以及我如何使用es解决问题
。
简介
ES简略介绍
es为什么能够解决我的问题
,我想要的搜索场景是,可以从用户输入的文本串中提取
出有用的匹配信息,然后到我的数据库中对待匹配的信息
进行匹配。命中即认为该数据是用户需要的,用户输入文本可能与数据库中的某段信息的文字部分
是完全一致的,但是文字顺序
是被打乱的。mysql数据库支持like,所以可以将用户输入文字串分割成每个字,然后用or
去拼接查询。这种查询效率和使用方式可想而知有多么恐怖。但是es不需要这么麻烦的使用姿势,es支持match
,可以对文本进行匹配搜索。为什么MySQL这么麻烦,而es看起来很方便呢?因为他们主要的应用场景就不同,所以底层的数据结构就不同。首先看看他们对数据的索引方式
:
MySQL的索引方式很简单,一条记录留存,如果指定了需要索引某个字段,就会将这个字段的值
和对应记录的ID
拿出来,存储到B+
树中,二分搜索可以对有序数据进行快速查找,但是如果使用like '%x%'
;可以看到无法判断要匹配文本的首字母了,也就是无法使用索引了,这样数据量一旦上来,查询效率会飞快下降。
es的索引方式中文一直叫做倒排索引
,什么叫倒排索引,在mysql中,索引的是这个字段的全文本,然后用全文本去匹配我们的输入,如果匹配不到就错了,换个数据继续匹配。这个思路就是,我们需要所有数据的全文本,然后挨个匹配。可现在的场景是需要这么做,你只需要给我输入的文本内有效部分
的有关数据即可。所以我们首先需要考虑将输入信息进行分割
、提取
。然后用提取出来的每部分
数据参与匹配。那有个想法,如果我存的数据,也按照这种分割-提取
来提前建立一份索引呢?那就可以用提取到的部分输入直接去匹配数据库里提前存储好的数据的索引。匹配到一个部分即认为命中
,匹配到多个部分认为相关度更高
,最终得分
也就越高。这种将文档的文本打散进行索引再反过来查询文档的,被称作倒排索引
。
ik分词器简介
既然有个数据库可以支持倒排索引,那么接下来就看看怎么对文本分词
,首先一个问题是为什么要分词
,如果不分词,我输入一段话,每个字都是一个token
。那如果我认为有些字按照一定的顺序组合起来有固定的含义,他们就成了词,词就意味着通用,我们在存储和使用时都会按照这个顺序。即他们也可以做token
。这样一份文档的token
数量就会减少,这样可以显著提升查询的效率。
但是这也有个问题,比如上文的内蒙大马
。如果我用了分词器,ik的通用词库里有蒙古、大马
,我现在用马
去搜索,命中结果集为空,因为这段文本被索引为蒙古
、大马
,你用马
是匹配不到大马
这个索引的。字是默认组词使用的,如果有单字也是可以用使用的特殊情况,可以在词典里添加这个单字,需要注意词的顺序,最短的词放在上面,否则由于分词器是不贪心
的,已经匹配了一个比较好的索引,就不去再考虑生成一个差的索引了。词典添加后还要注意不要使用ik_smart
类型的分析器,下文会有说明。如果你认为你的场景每个字都需要考虑,那就简单了,不要分词
,以改兼赈、两难自解
;
es本身不支持中文分词,ik分词器可以支持中文的分词,所以需要ik分词器。ik分词有两种type
:
ik_smart
:对文本进行粗粒度分词,比如蓝瘦香菇这个词,我如果词典里有蓝瘦、香菇、蓝瘦香菇。他的分词结果蓝瘦香菇;显然,他的索引数量会更少,也会丢掉更多数据的查询。
ik_max_word
,进行最粗粒度的分词,会列举所有的可能(但不包括已经被组词的字
,所以单字的特殊情况可以将它作为词来解决)。
每次更新词库都需要重启,这太费劲了,还好ik支持热更新词库。只需要在配置文件配置remote_ext_dict
即可。但是,更新词典后只对之后的新数据有效,旧有数据需要重建索引
,
使用
es的直接简单使用
- 创建索引
PUT /index_name
{"mappings": {"properties": {"ref_id": { "type": "long" },"ref_type": { "type": "integer" },"goods_name": { "type": "text","analyzer":"my_ik_analyzer","search_analyzer":"ik_max_word"},"param_value": { "type": "text","analyzer":"my_ik_analyzer","search_analyzer":"ik_max_word"}}}
}
- 删除索引
DELETE /index_name
- 新增或更新文档
POST /index_name/_doc/doc_id # 最后一位参数可以指定生成的文档ID
{
"ref_id": 1,
"ref_type":1,
"goods_name": "狗;犬;野狗;导盲犬",
"param_value": "中华田园犬;美国狗;吃狗粮;奥利给"
}
- 分析测试
POST /index_name/_analyze?pretty
{
"analyzer": "ik_max_word",
"text":"内蒙大马"
}
- 查询
POST /bws_price_library/_search?pretty
{"query":
{"bool":{"must": [{ "multi_match": {"query":"大马","fields":["goods_name^2","param_value"] #字段名后面的^n可以指定得分权重。}},{"term":{"ref_type":"101"}}]}
}}
es的查询
es的查询很负责,所以能覆盖非常多的场景。作者上面涉及 准确查询term
、匹配查询match
,多字段匹配查询multi_match
、布尔嵌套查询bool
,只做了简单的示例,很容易触类旁通。具体的使用方式作者有时间会慢慢补充。
es在java中使用
- 保存
XXXXIndex index = new XXXXIndex();index.setId(BwsPriceConstant.SPECS_REF_TYPE_PART+"_"+id);index.setRefId(id);index.setRefType(BwsPriceConstant.SPECS_FEE_TYPE_PART);index.setGoodsName("name");index.setParamValue("value");IndexCoordinates indexCoordinates = elasticsearchRestTemplate.getIndexCoordinatesFor(XXXXIndex.class);elasticsearchRestTemplate.save(index,indexCoordinates);
- 删除
elasticsearchRestTemplate.delete(id, XXXXIndex.class);
- 更新
IndexCoordinates indexCoordinates = elasticsearchRestTemplate.getIndexCoordinatesFor(XXXXIndex.class);Document document = Document.create();document.setId(index.getId());document.putIfAbsent("ref_id",index.getRefId());document.putIfAbsent("ref_type",index.getRefType());document.putIfAbsent("goods_name",index.getGoodsName());document.putIfAbsent("param_value",index.getParamValue());elasticsearchRestTemplate.update(UpdateQuery.builder(index.getId()).withDocument(document).build(),indexCoordinates);
- 查询
Pageable pageable = PageRequest.of(reqVo.getCurrentPage()-1, reqVo.getPageSize());Map<String, Float> fields = new HashMap<>();fields.put("goods_name",3.0f);fields.put("param_value",1.0f);// 查询实体使用构造器模式,multiMatchQuery.fields方法可以指定查询权重,查看构造方法可以看到默认是都给了1的权重。这个权重也可以在构建索引的时候指定,不过查询时指定的话会更灵活一些NativeSearchQuery build = new NativeSearchQueryBuilder().withPageable(pageable).withQuery(new BoolQueryBuilder().must(new TermQueryBuilder("ref_type", reqVo.getFeeType())).must(QueryBuilders.multiMatchQuery(reqVo.getName(), "goods_name", "param_value").fields(fields))).build();SearchHits<XXXXIndex> search = elasticsearchRestTemplate.search(build, XXXXIndex.class);List<SearchHit<XXXXIndex>> searchHits = search.getSearchHits();// SearchHit中的Content就是指定的类型对象
备注说明
在使用时建议做好数据的手动同步,以防万一
相关文章:

ES分词搜索
ES的使用 前言作者使用的版本作者需求 简介ES简略介绍ik分词器简介 使用es的直接简单使用es的查询 es在java中使用备注说明 前言 作者使用的版本 es: 7.17.27spring-boot-starter-data-elasticsearch: 7.14.2 作者需求 作者接到一个业务需求,我们系统有份数据被…...
深入掌握Node.js HTTP模块:从开始到放弃
文章目录 一、HTTP模块入门:从零搭建第一个服务器1.1 基础概念解析1.2 手把手创建服务器 二、核心功能深入解析2.1 处理不同请求类型2.2 实现文件下载功能 三、常见问题解决方案3.1 跨域问题处理3.2 防止服务崩溃3.3 调试技巧 四、安全最佳实践4.1 请求头安全设置4.…...

【数据库】并发控制
并发控制 在数据库系统,经常需要多个用户同时使用。同一时间并发的事务可达数百个,这就是并发引入的必要性。 常见的并发系统有三种: 串行事务执行(X),每个时刻只有一个事务运行,不能充分利用…...

Ansys Zemax | 手机镜头设计 - 第 2 部分:光机械封装
本文该系列文章将讨论智能手机镜头模组设计的挑战,涵盖了从概念、设计到制造和结构变形的分析。本文是四部分系列的第二部分,介绍了在 Ansys Speos 环境中编辑光学元件以及在整合机械组件后分析系统。案例研究对象是一家全球运营制造商的智能手机镜头系统…...
湖北理元理律师事务所债务优化实践:在还款与生活间寻找平衡支点
在个人债务规模持续扩大的社会背景下,如何科学管理债务正成为民生焦点。湖北理元理律师事务所通过其服务案例表明:债务优化的本质不是逃避责任,而是建立可持续的还款体系,让债务人保有基本生活尊严。 一、打破“越还越穷”的恶性…...

mcp-go v0.30.0重磅发布!Server端流式HTTP传输、OAuth支持及多项功能革新全面解读!
随着云原生应用和现代分布式系统需求的不断增长,高效、灵活且稳定的通信协议和客户端交互框架成为开发者关注的焦点。作为开源领域备受期待的项目之一,mcp-go再次迎来重要版本更新——v0.30.0正式发布!本次更新版本不仅实现了众多关键功能&am…...
解锁 MCP 中的 JSON-RPC:跨平台通信的奥秘
你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益: 了解大厂经验拥有和大厂相匹配的技术等希望看什么,评论或者私信告诉我! 文章目录 零、 背景一、RPC vs HTTP1.1 什么是RPC1.2 为什么需要 RPC?1.3 RPC 解决了什么…...
流复制(Streaming Replication)与自动故障转移(Failover)实战:用Patroni或Repmgr搭建生产级数据库集群
更多服务器知识,尽在hostol.com 嘿,各位PostgreSQL的“掌舵人”和数据“守护神”们!咱们都知道,PostgreSQL(简称PG)以其强大的功能、稳定性和开源的特性,赢得了越来越多开发者和企业的青睐。但…...

OpenGL Chan视频学习-10 Dealing with Errors in OpenGL
bilibili视频链接: 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站: docs.gl 说明: 1.之后就不再单独整理网站具体函数了,网站直接翻译会…...

美团启动618大促,线上消费节被即时零售传导到线下了?
首先,从市场推广与消费者吸引的角度来看,美团通过联合众多品牌开展大规模促销活动,并发放高额优惠券包,旨在吸引更多消费者参与购物。这种策略有助于提高平台的活跃度和交易量,同时也能够增强用户粘性。对于消费者而言…...

搭建 Select 三级联动架构-东方仙盟插件开发 JavaScript ——仙盟创梦IDE
三级级联开卡必要性 在 “东方仙盟” 相关插件开发中,使用原生 HTML 和 JavaScript 实现三级联动选择(如村庄 - 建筑 - 单元的选择)有以下好处和意义,学校管理: 对游戏体验的提升 增强交互性:玩家能够通…...

服务器如何配置防火墙管理端口访问?
配置服务器防火墙来管理端口访问,是保障云服务器安全的核心步骤。下面我将根据你使用的不同操作系统(Linux: Ubuntu/Debian/CentOS;Windows Server)介绍常用防火墙配置方法。 ✅ 一、Linux 防火墙配置(UFW / firewalld…...
Webhook入门
主要参考资料: 深入解析 Webhook:从原理到实践的全面指南: https://blog.csdn.net/weixin_43114209/article/details/144250750 目录 简介Webhook 与传统 API 调用的区别与轮询 (Polling) 的对比典型工作流程 简介 简单来说,Webhook 是一种“…...
LangChain整合Milvus向量数据库实战:数据新增与删除操作
导读:在AI应用开发中,向量数据库已成为处理大规模语义搜索和相似性匹配的核心组件。本文通过详实的代码示例,深入探讨LangChain框架与Milvus向量数据库的集成实践,为开发者提供生产级别的向量数据管理解决方案。 文章聚焦于向量数…...
LSTM+Transformer混合模型架构文档
LSTMTransformer混合模型架构文档 模型概述 本项目实现了一个LSTMTransformer混合模型,用于超临界机组协调控制系统的数据驱动建模。该模型结合了LSTM的时序建模能力和Transformer的自注意力机制,能够有效捕捉时间序列数据中的长期依赖关系和变量间的复…...
Symbol、Set 与 Map:新数据结构探秘
Symbol、Set 与 Map:新数据结构探秘 引言 ECMAScript 6 (ES6) 引入了三种强大的数据结构:Symbol、Set 与 Map,它们解决了 JavaScript 开发中的特定痛点,为我们提供了更多工具来处理复杂的数据操作。 Symbol:唯一标识…...

Spring Boot+Activiti7入坑指南初阶版
介绍 Activiti 是一个轻量级工作流程和业务流程管理 (BPM) 平台,面向业务人员、开发人员和系统管理员。其核心是一个超快且坚如磐石的 Java BPMN 2 流程引擎。它是开源的,并根据 Apache 许可证分发。Activiti 可以在任何 Java 应用程序、服务器、集群或云中运行。它与 Spri…...

如何在 Odoo 18 中创建 PDF 报告
如何在 Odoo 18 中创建 PDF 报告 Qweb 是 Odoo 强大的模板引擎,旨在轻松将 XML 数据转换为 HTML 文档。其功能特性包括基于属性的自定义、条件逻辑、动态内容插入及多样化的报告模板选项。这种多功能性使 Qweb 成为制作个性化、视觉吸引力强的报告、电子邮件和文档…...

【ROS2实体机械臂驱动】rokae xCoreSDK Python测试使用
【ROS2实体机械臂驱动】rokae xCoreSDK Python测试使用 文章目录 前言正文配置环境下载源码配置环境变量测试运行修改点说明实际运行情况 参考 前言 本文用来记录 xCoreSDK-Python的调用使用1。 正文 配置环境 配置开发环境,这里使用conda做python环境管理&…...
c/c++的opencv椒盐噪声
在 C/C 中实现椒盐噪声 椒盐噪声(Salt-and-Pepper Noise),也称为脉冲噪声(Impulse Noise),是数字图像中常见的一种噪声类型。它的特点是在图像中随机出现纯白色(盐)或纯黑色&#x…...
C++ TCP程序增加TLS加密认证
TCP为什么要增加TLS TCP程序添加TLS主要是为了解决TCP协议本身的安全缺陷。TCP作为传输层协议,虽然提供了可靠的数据传输,但它是明文传输,存在几个关键的安全问题: 数据泄露风险:TCP传输的数据完全暴露在网络中,任何能够监听网络流量的人都可以直接读取传输内容。这对于…...
构建一个“论文检索 + 推理”知识库服务,支持用户上传 PDF/LATEX 源码后,秒级检索并获得基于内容的问答、摘要、引用等功能
文章目录 1 总体目标 / Overall Goal2 数据管线 / Data Pipeline3 检索策略 / Retrieval Strategy4 服务切分 / Service Decomposition5 Agent & Prompt 设计 / Agent & Prompt6 核心功能 / Core Features7 评测与监控 / Evaluation & Monitoring8 面试亮点 / Inte…...

VLC-QT 网页播放RTSP
先看效果图,代码在文章末尾,包含源码,vlc-qt完整的库 环境说明:VS 2017 QTQt5.13.0 MSVC2017 32位 将vlc_install 目录下的bin,include,lib里所有的东西分别放在qt目录下 bin -> C:\Qt\Qt5.13.0\5.13.0\msvc2017\bin include->C:\Qt\Qt5.13.0\5.13.0\msvc201…...
for(auto a:b)和for(auto a:b)的区别
#include<iostream> using namespace std; int main() {string s( "hello world" );for (auto c:s)c t ;cout<<s<<endl; //结果为hello worldfor (auto &c:s)c t ;cout<<s<<endl; //结果为ttttttttttt }for(auto a:b)中b为一…...
第2章-12 输出三角形面积和周长(走弯路解法)
本题要求编写程序,根据输入的三角形的三条边a、b、c,计算并输出面积和周长。注意:在一个三角形中, 任意两边之和大于第三边。三角形面积计算公式:areas(s−a)(s−b)(s−c),其中s(abc)/2。 import math de…...
Caddy如何在测试环境中使用IP地址配置HTTPS服务
前言 在开发和测试环境中,我们经常需要搭建HTTPS服务进行测试。但通常Let’s Encrypt等证书颁发机构要求使用有效域名,不直接支持IP地址。本文将详细介绍如何使用Caddy在测试环境中通过IP地址配置HTTPS服务,使用自签名证书解决这一问题。 环…...
shell中与>和<相关的数据流重定向操作符整理
shell中与>和<相关的数据流重定向操作符整理 输出重定向操作符>>>2>2>>&> 或 >&&>> 输入重定向操作符<<<<<< 组合重定向2>&1 文件描述符相关重定向[n]< file 和 [n]> file>&- 和 <&…...

【航天远景 MapMatrix 精品教程】08 Pix4d空三成果导入MapMatrix
【航天远景 MapMatrix 精品教程】08 Pix4d空三成果导入MapMatrix 文章目录 【航天远景 MapMatrix 精品教程】08 Pix4d空三成果导入MapMatrix一、资料准备1.去畸变影像2.相机文件3.外方位元素二、创建工程1.新建工程2.导入照片3.编辑相机文件4.编辑外方位元素文件,导入外方位元…...

创建型设计模式之Prototype(原型)
创建型设计模式之Prototype(原型) 摘要: Prototype(原型)设计模式通过复制现有对象来创建新对象,避免重复初始化操作。该模式包含Prototype接口声明克隆方法、ConcretePrototype实现具体克隆逻辑ÿ…...

JNI开发流程
一. 引言 最近在做一个自己的项目,就是基于FastDDS封装一套JAVA库,让android和java应用可以使用dds的功能。 由于FastDDS是使用C编写的开源库,因此java的类库想要调用FastDDS的接口,需要额外编写一个JNI层的动态库对FastDDS的接口…...