Elasticsearch 第四期:搜索和过滤

 序

        2024年4月,小组计算建设标签平台,使用ES等工具建了一个demo,由于领导变动关系,项目基本夭折。其实这两年也陆陆续续接触和使用过ES,两年前也看过ES的官网,当时刚毕业半年多,由于历史局限性导致根本看不懂。因此趁着这个机会,在5月~6月期间,基本看了一遍ES的官方文档,先从整体梳理了ES的基础知识,共四期。

Elasticsearch 第一期:ES的前世今生-CSDN博客

Elasticsearch 第二期:基础的基础概念-CSDN博客

Elasticsearch 第三期:倒排索引,分析,映射-CSDN博客

Elasticsearch 第四期:搜索和过滤-CSDN博客

前言

这篇文章的内容是根据ES官方关于搜索的章节整理的。但目录结构做了重新整理。分别从相关性,搜索,过滤进行了介绍。具体如下:

相关性

ES搜索的本质其实是把文档根据搜索内容进行相关性排序。所以在介绍ES搜索之前,先简单介绍一下ES相关性。关于相关性的理论知识具体可以参考官网。当然相关性得分只是搜索排序的一种,还有特殊场景的排序方法,如地理位置邻近算法。

众所周知,查询语句会为每个文档生成一个评分: _score 。通常我们说的 相关性 是用来计算全文本字段的值相对于全文本检索词相似程度的算法。

Elasticsearch 的相似度算法被定义为:TF/IDF(检索词频率/反向文档频率) 。

检索词频率:检索词在该字段出现的频率。出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。

反向文档频率:每个检索词在全部索引中出现的频率。频率越高,计算相关时相关性的权重越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。

字段长度准则:该字段的长度是多少。长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大。

检索词频率

title:dog love person

很明显,dog在第二个文档中出现了2次,因此文档2相关性更强

title:dog love dog

反向文档频率

title:dog love person

当使用dog和person来搜索时,虽然文档2被命中了2次,但person在全部文档中出现了频率比dog少,因此计算person相关性权重的时候会更大

title:dog love dog

字段长度准则

title:dog love person

搜索love时可以名字两个文档,但文档2中的字段相对较短,其得分更高。

title:dog love dog

搜索

搜索的过程就是在全文字段中搜索到最相关的文档。搜索两个最重要的方面是:

相关性(Relevance)它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力

分析(Analysis)它是将搜索关键字和文档内容转换为有区别的、规范化的 词项(token) 的一个过程。 目的是为了(a)创建倒排索引 (b)查询倒排索引。

在Elasticsearch 7.x中,它提供了三种主要的文档检索方式:全文搜索、词项搜索和复合搜索。

全文搜索

简单查询

全文搜索是Elasticsearch最常见的搜索方式,主要用于搜索文本字段。用户只需要提供关键词,Elasticsearch就能自动地在索引中找到包含这些关键词的文档。在全文搜索中,Elasticsearch使用了一种名为“倒排索引”的数据结构,可以非常高效地执行搜索操作。

全文搜索主要通过match查询实现。match查询会对用户给出的关键词进行解析,然后进行分词处理。只要查询语句中的任意一个词项在文档中被匹配,该文档就会被检索到。

全文搜索经常用的命令包括:

match

匹配查询,用于单字段搜索

multi_match

在多个字段上反复执行相同查询

match
{"query": {"match": {"title":{"query":"BROWN DOG!","operator":and  //所有词项都要匹配时"minimum_should_match":"50%"}}}
}

上面是match搜索的一个用例。搜索内容可以是一个词项,也可以是多个词项。若是多个词项场景,这些词语会被解析成单个词,然后在倒序索引中进行精确(term)查找。默认是这些词之间的关系是or,即满足文档中包含其中一个词就会被找到。

match有两个参数来控制搜索操作和返回结果。

  1. operator:需要搜索的关键词必须全部出现

  2. minimum_should_match :最小匹配参数

有时候需要搜索的关键词必须全部出现,可以使用参数 operator ,设置为 and 。

若文档数量超多,可以对相关性设定阈值,而我们只希望返回相关性高的文档, 可以使用 minimum_should_match 最小匹配参数。该参数的值设置有两种方式,指定必须匹配的词项数用来表示一个文档是否相关。具体数值可以参考:

1. 设置为某个具体数字来制定匹配的词项数量

2. 将其设置为一个百分数:百分数可以设置为正值(75%)也可以设置为负值(-25%)。计算必须文档中要匹配的词项数量

75%

-25%

4个搜索关键词

4*75%=3

4-4*25%=3

4个搜索关键词

5*75%=3(向下取整)

5-5*25%=4(向下取整)

multi_match

multi_match 则是match在多字段查到的一个简便方式。可以在能在多个字段上反复执行相同查询。

{"query":{"multi_match": {"query": "BROWN DOG","fields":["title","body"]}}

短语近似匹配

简单查询中match 或者multi_match查询可以获得包含查询词条的文档。但搜索查询时没有考虑词语之间的关系(如:位置关系,词性关系),甚至都不能确定匹配到的内容是否来自同一个字段。

1. Java是一门很好的语言,很多工程师都喜欢使用.

2. Java工程师都很优秀.

用 match 搜索 Java 工程师 上面的两个文档都会得到匹配,但很明显,其实文档2是我们需要的可能性更大。

当使用分析器将文档内容和搜索关键词进行分词之后,理解分词之间的关系是一个复杂的难题。我们也无法通过更换查询方式或者底层存储结构来解决分词问题。但我们至少可以通过出现在彼此附近或者相邻的分词来判断分词之间的相关性

这就是短语匹配或者近似匹配的所属领域。对于短语匹配,match_phrase也是经常用的搜索方式之一。例如下面的例子:

{"query": {"match_phrase": {"title": {"query":"quick brown fox","slop":2}}}
}

对于与matchmulti_match查询不同的是,除了将查询关键字解析成一个词项,然后在倒排索引中进行搜索查询外,match_phrase还会比较快搜索词项之间的位置,最终结果只会保留 位置 与搜索词项相同的文档。 

精确短语匹配 或许是过于严格了。也许我们想要包含 “Java 高级 工程师” 的文档也能够匹配 “Java 工程师,” ,可以通过使用 slop 参数将灵活度引入短语匹配中。

slop 参数告诉 match_phrase 查询词条相隔多远时仍然能将文档视为匹配 。 相隔多远的意思是为了让查询和文档匹配你需要移动词条多少次。

词项搜索

词项搜索与全文搜索不同,查询不会对输入进行分词处理,而是将输入作为一个整体进行搜索。词项搜索方式本文整理了精确查找--term和部分匹配搜索。

精确查找和范围查找

我们首先来看最为常用的 term 查询和range查询。正如上面所说,词项搜索不会对输入进行分词处理,而是将输入作为一个整体,在倒排索引中查找准确的词项。term和range一般适用于用来处理数字(numbers)、布尔值(Booleans)、日期(dates)等。

term

查询某个字段等于搜索词的文档

"term":{ "address":"香港"}

查询地址等于'香港'的文档 

terms

查询某个字段里包含多个关键词的文档

terms":{   "address":["香港","北京"]}

查询地址等于"香港"或"北京"的

range

实现范围查询

"range": {             "age": {                 "from": 18,                 "to": 28,                 "include_lower": true,                 "include_upper": true             }         }

部分匹配

可以发现,以上提出的搜索查询方式都是针对倒排索引整个词的操作。即根据词项在倒排索引中进行匹配查找。也就是说只能查找倒排索引中存在的词,最小的单元为单个词。

但如果想匹配倒排索引中存在词项一部分, 如搜索Java的时候,也希望把JavaScript查出来。这个时候怎么办呢?这个便是接下来要解释的内容--部分匹配。

 部分匹配 允许用户指定查找词的一部分并找出所有包含这部分片段的结果。默认状态下, 部分匹配默认不做相关度评分计算,它只是将所有匹配的文档返回。部分匹配有三种方式,这三种方式也不会对搜索词进行分词:

  1. 前缀查询

  2. 通配符查询

  3. 正则表达式查询

prefix

不会在搜索之前分析查询字符串,它假定传入前缀就正是要查找的前缀。

"prefix": {"postcode": "W1"}

wildcard

使用标准的 shell 通配符查询: ? 匹配任意字符, * 匹配 0 或多个字符

"wildcard": {

            "postcode": "W?F*HW" ,

            "postcode": "W[0-9].+" }

regexp

正则式

{ "regexp": { "title": "br.*" }}

复合搜索

复合搜索是Elasticsearch中最强大的搜索方式之一,它允许用户组合多种查询条件,实现复杂的搜索需求。在Elasticsearch中,复合搜索主要通过bool查询实现。bool查询可以利用逻辑关系(如andornot)组合多个其他的查询,从而构建出复杂的查询条件。

除了bool查询,Elasticsearch还提供了其他一些复合查询方式,如filter查询、join查询等。这些查询方式可以进一步扩展复合搜索的能力,满足更复杂的搜索需求。

bool 过滤器一般由以下三部分组成:

{"bool" : {"must" :     [],"should" :   [],"must_not" : []}
}

must

 必须 匹配这些条件才能被包含进来。

must_not

 必须不 匹配这些条件才能被包含进来。

should

如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。

过滤

过滤和搜索不同,过滤不需要谈论相关性或得分。过滤得到的结果: 非是即否。它简单的对文档包括或排除处理。fliter可以单独使用,也可以结合bool复合搜索来实现功能更强大的操作。

Elasticsearch 会在运行过滤查询时执行多个操作,如执行下面语句时,Elasticsearch行为包含4步:

{ "filter":{"term":{"age": [3,63]},"term":{"price": 30}}
}
  1. 查找匹配文档.

term 查询在倒排索引中查找,获取包含该 term 的所有文档。

2. 创建 bitset.

过滤器会创建一个 bitset (一个包含 0 和 1 的数组),它描述了哪个文档会包含该 term 。匹配文档的标志位是 1 。如有四个文档,执行完"term":{"age": [3,63]}语句之后,会得到一个bitset 的值: [1,0,0,0] 。

3. 迭代 bitset(s)

一旦为每个查询生成了 bitsets ,Elasticsearch 就会循环迭代 bitsets 从而找到满足所有过滤条件的匹配文档的集合。一般来说先迭代稀疏的 bitset (因为它可以排除掉大量的文档)。

4. 增量使用计数.

Elasticsearch 能够缓存过滤查询从而获取更快的访问,而且过滤查询也不会计算相关行。因此,filter速度要快于query。

总结

本文先介绍了相关性的知识,然后从全文搜 索,词项搜索,复合搜索三方面来介绍了ES搜索的常见场景和操作。最后介绍了与搜索对应的过滤操作。

本文的内容意在梳理ES搜索操作,并未细究背后的原理,如相关性算法等。后续如果有需要会补充。当然,在实际应用中,要综合考虑具体场景来选择相应的搜索方式。

参考文档

https://www.cnblogs.com/qdhxhz/p/11493677.html

Elasticsearch 7.x文档检索的三大策略:全文搜索、词项搜索与复合搜索-百度开发者中心

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

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

相关文章

Java有没有goto语句

一、技术细节 Java作为一种广泛使用的编程语言,其设计哲学强调清晰、简洁和易于维护。在技术细节层面,Java确实支持goto语句作为关键字,但在实际编程中,goto语句并不被推荐使用。Java中的goto是保留字,主要用于两个场…

chrome-base源码分析(1)macros模块

Chrome-base源码分析(2)之Macros模块 Author:Once Day Date:2024年6月29日 漫漫长路,才刚刚开始… 全系列文章请查看专栏: 源码分析_Once-Day的博客-CSDN博客 参考文档: macros - Chromium Code SearchChrome base 库详解:工…

安全架构概述_2.安全架构的定义和范围

安全架构是架构面向安全性方向上的一种细分,比如细分领域含有运维架构、数据库架构等。如果安全性体现在产品上,那么,通常的产品安全架构、安全技术体系架构和审计架构可组成三道防线。 (1)产品安全架构:构…

ArtTS系统能力-通知的学习(3.1)

上篇回顾: ArtTS语言基础类库-容器类库内容的学习(2.10.2) 本篇内容: ArtTS系统能力-通知的学习(3.1) 一、 知识储备 1. 基础类型通知 按内容分成四类: 类型描述NOTIFICATION_CONTENT_BASIC_TEXT普通文…

2024 Parallels Desktop for Mac 功能介绍

Parallels Desktop的简介 Parallels Desktop是一款由Parallels公司开发的桌面虚拟化软件,它允许用户在Mac上运行Windows和其他操作系统。通过强大的技术支持,用户无需重新启动电脑即可在Mac上运行Windows应用程序,实现了真正的无缝切换。 二…

普元EOS学习笔记-创建精简应用

前言 本文依旧基于EOS8.3进行描述。 在上一篇文章《EOS8.3精简版安装》中,我们了解到普元预编译好的EOS的精简版压缩包,安装后,只能进行低开,而无法高开。 EOS精简版的高开方式是使用EOS开发工具提供的IDE,创建一个…

东软睿驰总裁兼CTO杜强受邀出席 CICV 2024智能网联汽车技术首脑(CTO)闭门峰会

近日,第十一届国际智能网联汽车技术年会(CICV 2024)在北京举办,会议期间组织智能网联汽车技术首脑(CTO)闭门峰会,邀请40余位技术领袖围绕智能网联汽车产业生态建设以及智能网联汽车数据、算力和…

SQL语句查询Cache数据库中数据时对时间怎样转换

使用东华医为HIS系统的用户都知道,Cache数据库中对于日期的存储为几万的数字,比如,今天就是相对于1841年1月1日的第多少万天,以这种形式进行表示;对于时间,也是以数字形式存储,比如,…

Python的numpy简单使用

1.可以调用引入numpy里面的函数,如add可以把俩数相加,也可以创建一个数组arr,arr.shape是数组arr的属性,如果后有跟()就是里面的一个函数 type()函数可以知道里面是什么类型 变量.shape可以知道这个变量是…

BLEU和SPICE:机器翻译与图像描述的自动评估方法详解

BLEU和SPICE:机器翻译与图像描述的自动评估方法详解 在机器翻译和图像描述领域,评估模型性能是一个重要且复杂的问题。为了有效地评估机器生成的文本质量,我们需要一种自动、快速且可靠的方法。BLEU(Bilingual Evaluation Unders…

基于决策树的旋转机械故障诊断(Python)

前置文章: 将一维机械振动信号构造为训练集和测试集(Python) https://mp.weixin.qq.com/s/DTKjBo6_WAQ7bUPZEdB1TA 旋转机械振动信号特征提取(Python) https://mp.weixin.qq.com/s/VwvzTzE-pacxqb9rs8hEVw import…

菲尔兹奖得主测试GPT-4o,经典过河难题未能破解!最强Claude 3.5回答离谱!

目录 01 大言模型能否解决「狼-山羊-卷心菜」经典过河难题? 02 加大难度:100只鸡、1000只鸡如何? 01 大言模型能否解决「狼-山羊-卷心菜」经典过河难题? 最近,菲尔兹奖得主Timothy Gowers分享了他测试GPT-4o的经历&a…

游戏推荐: 植物大战僵尸杂交版

下载地址网上一搜就有. 安装就能玩. 2是显血. 4显示植物血, 5是加速. 都是左手主键盘的按钮, 再按是取消. 比较刺激: ps: 设置里面还能打开自动收集阳光和金币.

视频融合共享平台LntonCVS统一视频接入平台智慧安防应用方案

安防视频监控平台LntonCVS是一款拥有强大拓展性和灵活部署能力的综合管理平台。它支持多种主流标准协议,包括国标GB28181、RTSP/Onvif、RTMP等,同时兼容各厂家的私有协议和SDK,如海康Ehome、海大宇等。LntonCVS不仅具备传统安防视频监控功能&…

深入解析Tomcat:Java Web服务器(上)

深入解析Tomcat:Java Web服务器(上) Apache Tomcat是一个开源的Java Web服务器和Servlet容器,用于运行Java Servlets和JavaServer Pages (JSP)。Tomcat在Java Web应用开发中扮演着重要角色。本文将详细介绍Tomcat的基本概念、安装…

遥远星辰中的觉醒:超大质量黑洞的苏醒

遥远星辰中的觉醒:超大质量黑洞的苏醒 在浩渺无垠的宇宙中,星辰的闪烁仿佛是时间的涟漪,穿越亿万年的距离,抵达我们的眼眸。而在这片星辰大海的深处,一个惊人的现象正在悄然上演——距离地球3.6亿光年之遥的星系中&am…

【C++】空指针访问成员函数

空指针访问成员函数 C中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针 如果用到this指针,需要加以判断保证代码的健壮性 class Animal { public:void fun1() {//正常的成员函数}void fun2() {if (this NULL) {return;//如果没有这个…

Django 一对一关系

作用: 两个数据库表建立外键关系当外键表的数据被删除时,主表的数据也会一并删除。 1,添加表模型 Test/app8/views.pyfrom django.db import modelsclass User(models.Model):username models.CharField(max_length50, uniqueTrue)email …

【代码随想录训练营】【Day 65】【图论-2】| 卡码 99

【代码随想录训练营】【Day 65】【图论-2】| 卡码 99 需强化知识点 深度搜索和广度搜索 题目 99. 岛屿数量 思想:遍历到为1的节点,再搜索标记,每遇到新的陆地节点,增加计数 深度搜索广度搜索:此处用 [] 作为待遍…

前端面试必备:深入解析Vue.js中v-if与v-show的原理与应用

前言 在Vue.js中,条件渲染是一个核心的概念,它允许我们根据数据的状态来动态地显示或隐藏元素。v-if和v-show是Vue.js提供的两个最常用的条件渲染指令,它们在表面上看起来很相似,但实际上在背后的工作原理和适用场景上有着显著的…