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

备注说明

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

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

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

相关文章

Axure设计案例——科技感立体柱状图

想让你的数据展示告别平淡无奇&#xff0c;成为吸引全场目光的焦点吗&#xff1f;快来瞧瞧这个Axure设计的科技感立体柱状图案例&#xff01;科技感设计风格借助逼真的立体效果打破传统柱状图的平面感&#xff0c;营造出一种令人眼前一亮的视觉震撼。每一个柱状体都仿佛是真实存…

恶意npm与VS Code包窃取数据及加密货币资产

60个npm包窃取系统敏感信息 安全研究人员在npm软件包注册表中发现60个恶意组件&#xff0c;这些组件能够收集主机名、IP地址、DNS服务器和用户目录信息&#xff0c;并将其发送至Discord平台控制的终端节点。据Socket安全研究员Kirill Boychenko上周发布的报告显示&#xff0c;…

leetcode 2359. 找到离给定两个节点最近的节点

给你一个 n 个节点的 有向图 &#xff0c;节点编号为 0 到 n - 1 &#xff0c;每个节点 至多 有一条出边。 有向图用大小为 n 下标从 0 开始的数组 edges 表示&#xff0c;表示节点 i 有一条有向边指向 edges[i] 。如果节点 i 没有出边&#xff0c;那么 edges[i] -1 。 同时…

1. pytorch手写数字预测

1. pytorch手写数字预测 1.背景2.准备数据集2.定义模型3.dataloader和训练4.训练模型5.测试模型6.保存模型 1.背景 因为自身的研究方向是多模态目标跟踪&#xff0c;突然对其他的视觉方向产生了兴趣&#xff0c;所以心血来潮的回到最经典的视觉任务手写数字预测上来&#xff0…

AWS WebRTC:获取ICE服务地址(part 2): ICE Agent的作用

上一篇&#xff0c;已经获取到了ICE服务地址&#xff0c;从返回结果中看&#xff0c;是两组TURN服务地址。 拿到这些地址有什么用呢&#xff1f;接下来就要说到WebRTC中ICE Agent的作用了&#xff0c;返回的服务地址会传给WebRTC最终给到ICE Agent。 ICE Agent的作用&#xf…

大数据时代的利剑:Bright Data网页抓取与自动化工具共建高效数据采集新生态

目录 一、为何要选用Bright Data网页自动化抓取——帮助我们高效高质解决以下问题&#xff01; 二、Bright Data网页抓取工具 - 网页爬虫工具实测 2.1 首先注册用户 2.2 首先点击 Proxies & Scraping &#xff0c;再点击浏览器API的开始使用 2.3 填写通道名称&#xff…

指纹识别+精准化POC攻击

开发目的 解决漏洞扫描器的痛点 第一就是扫描量太大&#xff0c;对一个站点扫描了大量的无用 POC&#xff0c;浪费时间 指纹识别后还需要根据对应的指纹去进行 payload 扫描&#xff0c;非常的麻烦 开发思路 我们的思路分为大体分为指纹POC扫描 所以思路大概从这几个方面…

【Day40】

DAY 40 训练和测试的规范写法 知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作业&#x…

【HTML-13】HTML表格合并技术详解:打造专业数据展示

表格是HTML中展示结构化数据的重要元素&#xff0c;而表格合并则是提升表格表现力的关键技术。本文将全面介绍HTML中的表格合并方法&#xff0c;帮助您创建更专业、更灵活的数据展示界面。 1. 表格合并基础概念 在HTML中&#xff0c;表格合并主要通过两个属性实现&#xff1a…

<uniapp><threejs>在uniapp中,怎么使用threejs来显示3D图形?

前言 本专栏是基于uniapp实现手机端各种小功能的程序,并且基于各种通讯协议如http、websocekt等,实现手机端作为客户端(或者是手持机、PDA等),与服务端进行数据通讯的实例开发。 发文平台 CSDN 环境配置 系统:windows 平台:visual studio code、HBuilderX(uniapp开…

如何制作全景VR图?

全景VR图&#xff0c;特别是720度全景VR&#xff0c;为观众提供一种沉浸式体验。 全景VR图能够捕捉场景的全貌&#xff0c;还能将多个角度的图片或视频无缝拼接成一个完整的全景视角&#xff0c;让观众在虚拟环境中自由探索。随着虚拟现实&#xff08;VR&#xff09;技术的飞速…

前端使用qrcode来生成二维码的时候中间添加logo图标

这个开源仓库可以让你在前端页面中生成二维码图片&#xff0c;并且支持调整前景色和背景色&#xff0c;但是有个问题&#xff0c;就是不能添加logo图片。issue&#xff1a; GitHub Where software is built 但是已经有解决方案了&#xff1a; add a logo picture Issue #21…

【C语言】函数指针及其应用

目录 1.1 函数指针的概念和应用 1.2 赋值与内存模型 1.3 调用方式与注意事项 二、函数指针的使用 2.1 函数指针的定义和访问 2.2 动态调度&#xff1a;用户输入驱动函数执行 2.3 函数指针数组进阶应用 2.4 函数作为参数的高阶抽象 三、回调函数 3.1 指针函数…

安装flash-attention失败的终极解决方案(WINDOWS环境)

想要看linux版本下安装问题的请走这里&#xff1a;安装flash-attention失败的终极解决方案&#xff08;LINUX环境&#xff09; 其实&#xff0c;现在的flash-attention不像 v2.3.2之前的版本&#xff0c;基本上不兼容WINDOWS环境。但是在WINDOWS环境安装总还是有那么一点不顺畅…

[C]基础16.数据在内存中的存储

博客主页&#xff1a;向不悔本篇专栏&#xff1a;[C]您的支持&#xff0c;是我的创作动力。 文章目录 0、总结1、整数在内存中的存储1.1 整数的二进制表示方法1.2 不同整数的表示方法1.3 内存中存储的是补码 2、大小端字节序和字节序判断2.1 什么是大小端2.2 为什么有大小端2.3…

Python 基于卷积神经网络手写数字识别

Ubuntu系统&#xff1a;22.04 python版本&#xff1a;3.9 安装依赖库&#xff1a; pip install tensorflow2.13 matplotlib numpy -i https://mirrors.aliyun.com/pypi/simple 代码实现&#xff1a; import tensorflow as tf from tensorflow.keras.models import Sequent…

ElectronBot复刻-电路测试篇

typec-16p 接口部分 USB1&#xff08;Type - C 接口&#xff09;&#xff1a;这是通用的 USB Type - C 接口&#xff0c;具备供电和数据传输功能。 GND 引脚&#xff08;如 A1、A12、B1、B12 等&#xff09;&#xff1a;接地引脚&#xff0c;用于提供电路的参考电位&#xff0…

ESP8266+STM32 AT驱动程序,心知天气API 记录时间: 2025年5月26日13:24:11

接线为 串口2 接入ESP8266 esp8266.c #include "stm32f10x.h"//8266预处理文件 #include "esp8266.h"//硬件驱动 #include "delay.h" #include "usart.h"//用得到的库 #include <string.h> #include <stdio.h> #include …

CDN安全加速:HTTPS加密最佳配置方案

CDN安全加速的HTTPS加密最佳配置方案需从证书管理、协议优化、安全策略到性能调优进行全链路设计&#xff0c;以下是核心实施步骤与注意事项&#xff1a; ​​一、证书配置与管理​​ ​​证书选择与格式​​ ​​证书类型​​&#xff1a;优先使用受信任CA机构颁发的DV/OV/EV证…

【前端】Twemoji(Twitter Emoji)

目录 注意使用Vue / React 项目 验证 Twemoji 的作用&#xff1a; Twemoji 会把你网页/应用中的 Emoji 字符&#xff08;如 &#x1f604;&#xff09;自动替换为 Twitter 风格的图片&#xff08;SVG/PNG&#xff09;&#xff1b; 它不依赖系统字体&#xff0c;因此在 Android、…