ElasticSearch(六)— 全文检索

一、match系列查询

前面讲到的query中的查询,都是精准查询。可以理解成跟在关系型数据库中的查询类似。match系列的查询,是全文检索的查询。会通过分词进行评分,匹配,再返回搜索结果。

1.1 match 查询

"query": {"match": {"elk": "Elasticsearch LogStash Kibana"}
}

查询字符串是“Elasticsearch LogStash Kibana”,被分析器分词之后,产生三个小写的单词:elasticsearch logstash kibana,然后根据分析的结果构造一个布尔查询,默认情况下,引擎内部执行的查询逻辑是:只要 elk 字段值中包含有任意一个关键字 elasticsearch 或 logStash 或 kibana,那么返回该文档。
匹配查询的行为受到两个参数的控制:
operator:表示单个字段如何匹配查询条件的分词
minimum_should_match:表示字段匹配的数量。
通过调整 operator 和 minimum_should_match 属性值,控制匹配查询的逻
辑条件,进而控制引擎返回的结果。默认情况下 operator 的值是 or,在构造查询时设置分词之间的逻辑运算符,如果设置为 and,那么只有分词的每个词都匹配的文档,才能返回。
对于 minimum_should_match 属性值,默认值是 1,如果设置其值为 2,表示分词必须匹配查询条件的数量为 2,这意味着,只要文档的 elk 字段包含任意两个关键字,就满足查询条件,但是如果文档中只有 1 个关键字,这个文档就不满足条件。
例如:

POST indexname/_search{"query": {"match": {"message": {"query": "firefox chrome","operator": "and"}}}
}
或者:
POST indexname/_search{"query": {"match": {"message": {"query": "firefox chrome","minimum_should_match": 2}}}
}

只会返回文档中message字段同时包含firefox和chrome的文档,而只包含其中之一的不会返回。

1.2 multi_match 查询

多个字段上执行匹配相同的查询,叫做"multi_match"查询。比如:

POST indexname/_search{"query": {"multi_match": {"query": "AT","fields": ["DestCountry","OriginCountry"]}}
}

请求将同时检索文档中 DestCountry 和 OriginCountry 这两个字段,只要有一个字段包含 AT 词项该文档就满足查询条件。

1.3 match_phrase 查询

当你希望寻找邻近的单词时,match_phrase 查询可以帮你达到目的。比如:
假设我们要找到 title 字段包含这么一段文本“quick brown fox”的文档,然后我们用

GET indexname/_search{"query": {"match_phrase": {"title": "quick brown fox"}}
}

match_phrase 查询首先解析查询字符串来产生一个词条列表。然后会搜索所有的词条,但只保留包含了所有搜索词条的文档,并且词条的位置要邻接。
但是对于

GET /my_index/my_type/_search{"query": {"match_phrase": {"title": "quick fox"}}
}

这个查询查询不会匹配我们的任何文档,因为没有文档含有邻接在一起的
quick 和 fox 词条。也就是说,匹配的文档必须满足:
1、quick、brown 和 fox 必须全部出现在 title 字段中。
2、brown 的位置必须比 quick 的位置大 1。
3、fox 的位置必须比 quick 的位置大 2。

如果以上的任何一个条件没有被满足,那么文档就不能被匹配。
精确短语(Exact-phrase)匹配也许太过于严格了。也许我们希望含有"quick
brown fox"的文档也能够匹配"quick fox"查询,即使位置并不是完全相等的。
我们可以在短语匹配使用 slop 参数来引入一些灵活性:

GET /my_index/my_type/_search{"query": {"match_phrase": {"title": {"query": "quick fox","slop": 1}}}
}

match_phrase_prefix 查询
被称为基于前缀的短语匹配,比如:

{"match_phrase_prefix": {"brand": "johnnie walker bl"}
}

这种查询的行为与 match_phrase 查询一致,不同的是它将查询字符串的最
后一个词作为前缀使用,换句话说,可以将之前的例子看成如下这样:
johnnie跟着 walker,跟着以 bl 开始的词。
或者可以干脆理解为: “johnnie walker bl*”。
与 match_phrase 一样,它也可以接受 slop 参数(参照 slop )让相对词
序位置不那么严格。
prefix 查询存在严重的资源消耗问题,短语查询的这种方式也同样如此。前
缀 a 可能会匹配成千上万的词,这不仅会消耗很多系统资源,而且结果的用处也不大。
可以通过设置 max_expansions 参数来限制前缀扩展的影响,一个合理的值是 50 ,这也是系统默认的值:

{"match_phrase_prefix": {"brand": {"query": "johnnie walker bl","max_expansions": 50}}
}

二、模糊查询、纠错与提示器

2.1 编辑距离算法

在 Elasticsearch 基于全文的查询中,除了与短语相关的查询以外,其余查询都包含有一个名为 fuzziness 的参数用于支持模糊查询。Elasticsearch 支持的模糊查询与 SQL 语言中模糊查询还不一样,SQL 的模糊查询使用“% keyword%"的形式,效果是查询字段值中包含 keyword 的记录。

Elaticsearch 支持的模糊查询比这个要强大得多,它可以根据一个拼写错误的词项匹配正确的结果,例如根据firefix 匹配 firefox。在自然语言处理领域,两个词项之间的差异通常称为距离或编辑距离,距离的大小用于说明两个词项之间差异的大小。

编辑距离的算法有多种,在 Elasticsearch 中主要使用 Levenshtein 和 NGram两种。其他与此相关的算法也都是在这两种算法基础上进行的改造,基本思想都是一致的。所以理解这两个算法的核心思想是学习这部分内容的关键。

Levenshtein 与 NGram
Levenshein算法是前苏联数学家 Vladimir Levenshein在1965 年开发的一套算法, 这个算法可以对两个字符申的差异程度做量化。量化结果是一一个正整数,反映的是一个字符申变成另一个字符申最少需要多少次的处理。由于 Levenshtein算法是最为普遍接受的编辑距离算法,所以在很多文献中如果没有特殊说明编辑距离算法就是指 Levenshtein 算法。

在 Levenshtein 算法中定义了三种字符操作,即替换、插人和删除,后来又
由其他科学家补充了一个换位操作。在转换过程中,每执行次操作编辑距离就加1, 编辑距离越大越能说明两个字符串之间的差距大。

比如从 firefix 到 firefox 需要将“i"替换成“o”, 所以编辑距离为 1;而从 fax
到 fair 则需要将“x”替换为“i"并在结尾处插人“r”,所以编辑距离为 2。显然
在编辑距离相同的情况下,单词越长错误与正确就越接近。比如编辑距离同样为2 的情况下,从 fax 到 fair 与从 elascsearxh 到 elasticsearch,后者elastesearsh 是由拼写错误引起的可能性就更大此。所以编辑距离这种量化标准一般还需要与单词长度结合起来 明虑,在一些极端情况下编辑距离还应该设置为 0,比如像 at、on 这类长度只有 2 的短单词。

NGram 一般是指 N 个连续的字符,具体的字符个数被定义为 NGram 的 size。size 为 1 的 NGram 称为 Unigram, size 为 2 时称为 Bigram,而 size 为 3 时则称为Trigram。如果 NGram 处理的单元不是字符而是单词,一般称之为 Shingle。使用NGram 计算编辑距离的基本思路是让字符串分解为 NGram,然后比较分解后共有 NGram 的数量。假设有 a、b 两个字符申,则 NGram 距离的具体运算公式为:

ngram( a )+ngram(b) -2 * ngram(a)∩ngram( b)

ngram(a)和 ngram(b)代表 a、b 两个字符串 NGram 的数量; ngram(a) ∩
ngram(b)则是两者共有 NGram 的数量。
例如按 Bigram 处理 firefix 和 firefox 两个单词,分别为“fi,ir,re, ef, fi,ix”和“fi,ir, re, ef, fi, ox"。 那么两个字符申的 Bigram 个数都为 6,而共有 Bigram 为 4,则最终 NGram 距离为 6+6-2x4=4。
在应用上,Levenshtein 算法更多地应用于对单个词项的模糊查询上,而
NGram 则应用于多词项匹配中。Elasticseareh 同时应用了两种算法。

2.2 模糊查询

返回包含与搜索字词相似的字词文档;为了找到相似的术语,fuzzy 查询将
在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。查询然后返回每个扩展的完全匹配。
比如:

get indexname/_search{"query": {"fuzzy": {"message": {"value": "firefix","fuzziness": "1"}}}
}

我们想找到文档中 message 字段包含 firefox,而查询条件中给出的是 firefix,因为两者的编辑距离为 1,所以包含 firefox 的文档依然可以找到,但是,如果使用 firefit,因为编辑距离为 2,则不会找到任何文档。

相关的参数有:
value: 必填项,希望在 field 中找到的术语。
fuzziness: 选填项,匹配允许的最大编辑距离;可以被设置为“0”, “1”,“2”或“auto”。“auto”是推荐的选项,它会根据查询词的长度定义距离。
max_expansions: 选填项,创建的最大变体项,默认为 50。应该避免使用较大的值,尤其是当 prefix_length 参数值为 0 时,如果过多,会影响查找性能。
prefix_length: 选填项,创建扩展时保留不变的开始字符数。默认为 0。
transpositions: 选填项,指示编辑是否包括两个相邻字符串的转置(ab→ba)。默认为 true。

2.3 纠错与提示器

纠错是在用户提交了错误的词项时给出正确词项的提示,而输人提示则是在
用户输人关键字时给出智能提示,甚至可以将用户未输人完的内容自动补全。大多数互联网搜索引擎都同时支持纠错和提示的功能,比如在用户提交了错误的搜索关键字时会提示:“ 你是不是想查找…”.而在用户输人搜索关键字时还能自动弹出提示框将用户可能要输人的内容全都列出来供用户选择。

Elasticsearch 也同时支持纠错与提示功能,由于这两个功能从实现的角度来说并没有本质区别,所以它们都由一种被称为提示器或建议器( Suggester)的特殊检索实现。由于输人提示需要在用户输人的同时给出提示词,所以这种功能要求速度必须快,否则就失去了提示的意义。在实现上,输人提示是由单独的提示器完成。而在使用上,提示器则是通过检索接口_ search 的一个参数设置,例如:

POST indexname/_search?filter_path=suggest{"suggest": {"msg-suggest": {"text": "firefit chrom","term": {"field": "message"}}}
}

在示例中,search 接口的 suggest 参数中定义了一个提示 msg- suggest,并通过 text 参数给出需要提示的内容。另一个参数 term 实际上是一种提示器的名称,它会分析 text 参数中的字符串并提取词项,再根据 Levenshtein 算法找到满足编辑距离的提示词项。所以在返回结果中会包含一个 suguggest 字段,其中列举了依照 term 提示器找到的提示词项:
在这里插入图片描述

2.3 提示器

Elaticearch 提供了三种提示器,它们在本质上都是基于编辑距离算法。下面就来看看这此提示器如何使用。
term 提示器
这种提示器默认使用的算法是称为 internal 的编辑距离算法。intermal 算法本质上就是 Levenshtein 算法,但根据 Elasticsearch 索引特征做了一些优化而效率更高,可以通过 string distance 参数更改算法。
term 提示器使用的编辑距离可通过 max
edits 参数设置,默认值为 2。

phrase 提示器
terms 会将需要提示的文本拆分成词项,然后对每一个词项做单独的提示,
而 phrase 提示器则会使用整个文本内容做提示。所以在 phrase 提示器的返回结果中,不会看到一个词项一个词项的提示,而是针对整个短语的提示。但从使用的角度来看几乎是一样的,例如:

POST indexname/_search{"suggest": {"msg-suggest": {"text": "firefix with chrime","phrase": {"field": "message"}}}
}

在这里插入图片描述
但不要被 phrase 提示器返回结果欺骗,这个提示器在执行时也会对需要提
示的文本内容做词项分析,然后再通过 NGram 算法计算整个短语的编辑距离。所以本质上来说,phrase 提示是基于 term 提示器的提示器,同时使用了Levenshtein 和 NGram 算法。

completion 提示器
completion 提示器一般应用于输人提示和自动补全,也就是在用户输人的同时给出提示或补全未输入内容。这就要求 completion 提示器必须在用户输人结束前快速地给出提示,所以这个提示器在性能上做了优化以达到快速检索的目的。
首先要求提示词产生的字段为 completion 类型,这是一种专门为completion提示器而设计的字段类型,它会在内存中创建特殊的数据结构以满足快速生成提示词的要求。例如在示例中创建了 aricles 索引,并向其中添加了 1 份文档:

PUT articles{"mappings": {"properties": {"author": {"type": "keyword"},"content": {"type": "text"},"suggestions": {"type": "completion"}}}
}
POST articles/_doc/{"author": "taylor","content": "an introduction of elastic stack and elasticsearch","suggestions": {"input": ["elastic stack","elasticsearch"],"weight": 10}
}
POST articles/_doc/{"author": "taylor","content": "an introduction of elastic stack and elasticsearch","suggestions": [{"input": "elasticsearch","weight": 30},{"input": "elastic stack","weight": 1}]
}

在向 completion 类型的字段添加内容时可以使用两个参数,input 参数设置
字段实际保存的提示词;而 weight 参数则设置了这些提示词的权重,权重越高它在返回的提示词中越靠前。在示例 5-29 中给出了两种设置提示词权重的方式,第一种是将一组提示词的权重设置为统一值,另一种则是分开设置它们的权重值。需要注意的是,completion 类型字段保存的提示词是不会分析词项的。
completion 提示器专门用于输人提示或补全,它根据用户已经输人的内容提示完整词项,所以在 completion 提示器中没有 text 参数而是使用 prefix 参数。例如:

POST articles/_search{"_source": "suggest","suggest": {"article_suggestion": {"prefix": "ela","completion": {"field": "suggestions"}}}
}

总结一下,term 和 phrase 提示器主要用于纠错,term 提示器用于对单个词项的纠错而 phrase 提示器则主要针对短语做纠错。completion 提示器是专门用于输人提示和自动补全的提示器,在使用上依赖前缀产生提示并且速度更快。

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

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

相关文章

c++笔记4

目录 深度优先搜索DFS DFS的复杂度 DFS与递归 递归与暴力枚举 递归树 DFS与栈 DFS的搜索剪枝 搜索剪枝与优化 可行性剪枝 最优化剪枝 减少等效的分支 优化搜索顺序 搜索的记忆化 搜索的复杂度 大多时候,搜索的复杂度都是指数级的。各种剪枝方案&#…

Flink 技术与应用(一)

Flink技术与应用(初级篇) 起源 Apache Flink 是一个开源的大数据处理框架,其起源可以追溯到一个名为 Stratosphere 的研究项目,旨在建立下一代大数据分析引擎,2010 年,从 Stratosphere 项目中分化出了 Fl…

「Unity3D」场景中的距离单位Unit与相关设置PixelsToUnits、PixelsPerUnit

GameObject在场景的位置Position,并没有明确是什么具体单位——如:Transform的x、y、z,或RectTransform的PosX、PosY、PosZ。而RectTransform在面板上显示的Width和Height,也没有具体单位,其实并不是像素。 事实上&am…

百易云资产管理运营系统 comfileup.php 文件上传致RCE漏洞复现(XVE-2024-18154)

0x01 产品简介 百易云资产管理运营系统,是专门针对企业不动产资产管理和运营需求而设计的一套综合解决方案。该系统能够覆盖资产的全生命周期管理,包括资产的登记、盘点、评估、处置等多个环节,同时提供强大的运营分析功能,帮助企业优化资产配置,提升运营效率。 0x02 漏…

C++内存管理(候捷)第五讲 笔记

GNU C对allocators的描述 new_allocator 和malloc_allocator,它们都没有特别的动作,无非底部调用operator new和malloc。它们没有用内存池 区别:::operator new是可重载的 智能型的allocator,使用内存池,分一大块然后…

【PyTorch】基于YOLO的多目标检测项目(一)

【PyTorch】基于YOLO的多目标检测项目(一) 【PyTorch】基于YOLO的多目标检测项目(二) 目标检测是对图像中的现有目标进行定位和分类的过程。识别的对象在图像中显示有边界框。一般的目标检测方法有两种:基于区域提议的…

如何找到最快解析速度的DNS

如何找到最快解析速度的DNS DNS,即域名系统(Domain Name System),是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使用户更方便地访问互联网,而不用记住能够被机器直接读取的IP数…

6.乳腺癌良性恶性预测(二分类、逻辑回归、PCA降维、SVD奇异值分解)

乳腺癌良性恶性预测 1. 特征工程1.1 特征筛选1.2 特征降维 PCA1.3 SVD奇异值分解 2. 代码2.1 逻辑回归、二分类问题2.2 特征降维 PCA2.3 SVD奇异值分解 1. 特征工程 专业上:30个人特征来自于临床一线专家,每个特征和都有医学内涵;数据上&…

7月25日JavaSE学习笔记

线程的生命周期中,等待是主动的,阻塞是被动的 锁对象 创建锁对象,锁对象同一时间只允许一个线程进入 //创建锁对象Lock locknew ReentrantLock(true);//创建可重入锁 可重入锁:在嵌套代码块中,锁对象一样就可以直接…

进销存系统开发,进销存源码解析,添加商品选择商品

点击添加商品信息(可以) (关键字范围:商品名称,简拼,条形码,SKU,规格,参数,尺寸,接口,CPU,品牌) function cwpd_selSaleGoodsNewMore_Vtax2024(domid,width…

sed利用脚本处理文件

一、sed是什么 sed 命令是利用脚本来处理文本文件。它可以依照脚本的指令来处理、编辑文本文件。主要用来自动编 辑一个或多个文件、简化对文件的反复操作、编写转换程序等。 二、sed的原理 读入新的一行内容到缓存空间; 从指定的操作指令中取出第一条指令&…

【时时三省】(C语言基础)分支语句2

山不在高,有仙则名。水不在深,有龙则灵。 ——csdn时时三省 多分支语句 if(表达式1) 语句1; else if(表达式2) 语句2; else 语句3; 如果表达式1成立语句1会执行 如果不成立表达式2执行 如果表达式2成…

【运维笔记】数据库无法启动,数据库炸后备份恢复数据

事情起因 在做docker作业的时候,把卷映射到了宿主机原来的mysql数据库目录上,宿主机原来的mysql版本为8.0,docker容器版本为5.6,导致翻车。 具体操作 备份目录 将/var/lib/mysql备份到~/mysql_backup:cp /var/lib/…

Multiview LM-ICP 配准算法

Multiview LM-ICP 配准算法针对一些大型的物体(比如建筑物)或者需要精细化建模的物体(比如某个文物),仅仅进行成对的配准难以还原物体的全貌和细节。所以,多个视角的配准十分关键。 多视角的配准存在以下两…

[STM32]FlyMcu同时烧写BootLoader和APP文件-HEX文件组成

目录 一、前言 二、HEX文件的格式 三、组合HEX文件 四、使用FlyMcu烧录 一、前言 如题,BootLoader每次烧写都是全部擦除,当我们烧写APP程序的时候,BootLoader程序将不复存在,很多开发者或许只有USB转TTL模块,没有其…

grep命令搜索部分命令

首先 然后可以输入|以及grep命令 比如 bjobs| grep "3075*"bjobs| grep "3075"这个结果是这样的,

MYSQL 第四次作业

任务要求: 具体操作: 新建数据库: mysql> CREATE DATABASE mydb15_indexstu; Query OK, 1 row affected (0.01 sec) mysql> USE mydb15_indexstu; Database changed 新建表: mysql> CREATE TABLE student( ->…

遇到总条数count(*)返回不了数据

文章目录 前提1.准备数据1.1 建表语句1.2 插入数据 2.程序代码3.返回结果与分析4.验证 前提 获取h_user表中count(*)字段的值打印出来,打印出来是0,数据库中执行sql返回不是0。端点调试找到原因。下面先把数据库表数据及程序贴出来。 1.准备数据 1.1 …

CSS技巧专栏:一日一例 12 -纯CSS实现边框上下交错的按钮特效

CSS技巧专栏:一日一例 12 -纯CSS实现边框上下交错的按钮特效 大家好,今天我们来做一个上下边框交错闪动的按钮特效。 本例图片 案例分析 虽说这按钮给人的感觉就是上下两个边框交错变换了位置,但我们都知道border是没法移动的。那么这个按…

【无标KaiwuDB CTO 魏可伟:差异化创新,面向行业的多模架构题】

2024年7月16日,KaiwuDB CTO 魏可伟受邀于 2024 可信数据库发展大会主论坛发表演讲《多模一库 —— KaiwuDB 的现代数据库架构探索》,以下是演讲精华实录。 多模数据库 是顺应时代发展与融合趋势的产物 数据模型最早始于网状模型和层次模型,…