ES分词搜索

news2025/6/3 7:28:42

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就是指定的类型对象

备注说明

在使用时建议做好数据的手动同步,以防万一

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

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

相关文章

【数据库】并发控制

并发控制 在数据库系统&#xff0c;经常需要多个用户同时使用。同一时间并发的事务可达数百个&#xff0c;这就是并发引入的必要性。 常见的并发系统有三种&#xff1a; 串行事务执行&#xff08;X&#xff09;&#xff0c;每个时刻只有一个事务运行&#xff0c;不能充分利用…

Ansys Zemax | 手机镜头设计 - 第 2 部分:光机械封装

本文该系列文章将讨论智能手机镜头模组设计的挑战&#xff0c;涵盖了从概念、设计到制造和结构变形的分析。本文是四部分系列的第二部分&#xff0c;介绍了在 Ansys Speos 环境中编辑光学元件以及在整合机械组件后分析系统。案例研究对象是一家全球运营制造商的智能手机镜头系统…

mcp-go v0.30.0重磅发布!Server端流式HTTP传输、OAuth支持及多项功能革新全面解读!

随着云原生应用和现代分布式系统需求的不断增长&#xff0c;高效、灵活且稳定的通信协议和客户端交互框架成为开发者关注的焦点。作为开源领域备受期待的项目之一&#xff0c;mcp-go再次迎来重要版本更新——v0.30.0正式发布&#xff01;本次更新版本不仅实现了众多关键功能&am…

OpenGL Chan视频学习-10 Dealing with Errors in OpenGL

bilibili视频链接&#xff1a; 【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p5&vd_source44b77bde056381262ee55e448b9b1973 函数网站&#xff1a; docs.gl 说明&#xff1a; 1.之后就不再单独整理网站具体函数了&#xff0c;网站直接翻译会…

美团启动618大促,线上消费节被即时零售传导到线下了?

首先&#xff0c;从市场推广与消费者吸引的角度来看&#xff0c;美团通过联合众多品牌开展大规模促销活动&#xff0c;并发放高额优惠券包&#xff0c;旨在吸引更多消费者参与购物。这种策略有助于提高平台的活跃度和交易量&#xff0c;同时也能够增强用户粘性。对于消费者而言…

搭建 Select 三级联动架构-东方仙盟插件开发 JavaScript ——仙盟创梦IDE

三级级联开卡必要性 在 “东方仙盟” 相关插件开发中&#xff0c;使用原生 HTML 和 JavaScript 实现三级联动选择&#xff08;如村庄 - 建筑 - 单元的选择&#xff09;有以下好处和意义&#xff0c;学校管理&#xff1a; 对游戏体验的提升 增强交互性&#xff1a;玩家能够通…

服务器如何配置防火墙管理端口访问?

配置服务器防火墙来管理端口访问&#xff0c;是保障云服务器安全的核心步骤。下面我将根据你使用的不同操作系统&#xff08;Linux: Ubuntu/Debian/CentOS&#xff1b;Windows Server&#xff09;介绍常用防火墙配置方法。 ✅ 一、Linux 防火墙配置&#xff08;UFW / firewalld…

Spring Boot+Activiti7入坑指南初阶版

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

如何在 Odoo 18 中创建 PDF 报告

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

【ROS2实体机械臂驱动】rokae xCoreSDK Python测试使用

【ROS2实体机械臂驱动】rokae xCoreSDK Python测试使用 文章目录 前言正文配置环境下载源码配置环境变量测试运行修改点说明实际运行情况 参考 前言 本文用来记录 xCoreSDK-Python的调用使用1。 正文 配置环境 配置开发环境&#xff0c;这里使用conda做python环境管理&…

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…

【航天远景 MapMatrix 精品教程】08 Pix4d空三成果导入MapMatrix

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

创建型设计模式之Prototype(原型)

创建型设计模式之Prototype&#xff08;原型&#xff09; 摘要&#xff1a; Prototype&#xff08;原型&#xff09;设计模式通过复制现有对象来创建新对象&#xff0c;避免重复初始化操作。该模式包含Prototype接口声明克隆方法、ConcretePrototype实现具体克隆逻辑&#xff…

JNI开发流程

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

STM32G4 电机外设篇(二) VOFA + ADC + OPAMP

目录 一、STM32G4 电机外设篇&#xff08;二&#xff09; VOFA ADC OPAMP1 VOFA1.1 VOFA上位机显示波形 2 ADC2.1 用ADC规则组对板载电压和电位器进行采样 3 OPAMP&#xff08;运放&#xff09;3.1 结合STM32内部运放和ADC来完成对三相电流的采样3.2 运放电路分析 附学习参考…

微服务难题?Nacos服务发现来救场

文章目录 前言1.什么是服务发现2.Nacos 闪亮登场2.1 服务注册2.2 服务发现 3.Nacos 的优势3.1 简单易用3.2 高可用3.3 动态配置 4.实战演练4.1安装 Nacos4.2 服务注册与发现示例代码&#xff08;以 Spring Boot 为例&#xff09; 总结 前言 大家好&#xff0c;我是沛哥儿。今天…

C# 结合PaddleOCRSharp搭建Http网络服务

Windows打开端口&#xff1a; 控制面板 > 系统和安全 > 防火墙> 高级设置 → 入站规则 → 右侧选择 → 新建规则 → 端口 → 协议类型 TCP→ 端口 using System; using System.Drawing; using System.IO; using System.Net; using System.Text; using System.Threadi…

【连接器专题】SD卡座规格书审查需要审哪些方面?

在审查SD卡座规格书时,我们需要考虑哪些方面? 首先在拿到一份SD卡座的详细规格书时,一般供应商给到的规格书中包括了一些基础信息、产品图纸信息、技术参数信息,同时有些供应商会给出产品可靠性测试报告。因此我们会从这几个要素去看规格书。 基础信息 基础信息一般会给变更…

eBest智能价格引擎系统 助力屈臣氏饮料落地「价格大脑」+「智慧通路」数字基建​

从价格策略到终端执行&#xff0c;数字化正在重构饮料行业竞争壁垒&#xff01; 近日&#xff0c;eBest为屈臣氏饮料提供的智能价格引擎系统已正式上线并投入运营。同时&#xff0c;基于eBest SFA方案且与屈臣氏饮料业务场景深度耦合的Smart Field Operation智慧通路项目正式启…

Kettle 远程mysql 表导入到 hadoop hive

kettle 远程mysql 表导入到 hadoop hive &#xff08;教学用 &#xff09; 文章目录 kettle 远程mysql 表导入到 hadoop hive创建 对象 执行 SQL 语句 -mysql 导出 CSV格式CSV 文件远程上传到 HDFS运行 SSH 命令远程登录 run SSH 并执行 hadoop fs -put 建表和加载数据总结 创…