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,一经查实,立即删除!

相关文章

Linux 大页修改

随笔记录 目录 1. 背景介绍 2. 麒麟SP1 系统修改大页 2.1 查询大页信息 2.2 通过kernel cmdline配置大页 2.3 生成配置 2.4 查看配置是否生效 2.5 查询大页是否配置成功 3. CenOS 系统修改大页 1. 背景介绍 若操作系统当前Hugepagesize不是2048kB,则只能…

SSM框架整合——常用方式整合SSM框架(三)Spring和MyBatis整合

一、Spring和MyBatis的整合步骤 Spring和MyBatis的整合可以分为2步来完成,首先搭建Spring环境,然后整合MyBatis到Spring环境中。框架环境包含框架对应的依赖和配置文件,其中Spring的依赖、MyBatis的依赖、Spring和MyBatis整合的依赖&#xf…

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…

Java 中对象List 转map实践

class MyObject {Long id;String name;// Constructorpublic MyObject(Long id, String name) {this.id id;this.name name;}// Getterspublic Long getId() {return id;}public String getName() {return name;} }第一种 List 转 Map<Long, String> List<MyObject…

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

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

用Python移除Word文档中的宏

Word文档作为最常用的电子文档格式之一&#xff0c;经常被用来作为内容分享工具&#xff0c;在网络中或设备之间进行传输&#xff0c;其安全性也需要受到关注。宏是可嵌入Word文档中的一种VBA迷你程序&#xff0c;用来执行一些自动化操作。虽然宏可以提高工作效率&#xff0c;但…

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

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

嵌入式系统面试宝典:常见问题与答案解析

1. 什么是嵌入式系统&#xff1f; 答案: 嵌入式系统是一种专用的计算机系统&#xff0c;它被设计用于执行特定的任务。它通常包含硬件组件&#xff08;如微控制器或微处理器&#xff09;和嵌入在硬件中的软件。 2. 请解释中断和轮询的区别。 答案: 中断是一种异步事件&#…

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

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

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

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

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

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

7月25日JavaSE学习笔记

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

探索PostgreSQL的GUI工具:提升数据库管理效率

在当今快速发展的技术世界中&#xff0c;数据库管理是任何软件开发项目的核心部分。PostgreSQL&#xff0c;作为一款功能强大的开源关系型数据库管理系统&#xff0c;因其稳定性、可靠性和高度的可扩展性而广受开发者和数据库管理员的青睐。然而&#xff0c;尽管PostgreSQL自带…

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

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

uniapp 小程序实现类似抖音的简易刷视频功能

uniapp 小程序实现类似抖音的简易刷视频功能 先上视频 20240725-163843 直接上代码 代码中使用的是 uniapp 组件 swiper slider slider swiper 2. 代码中使用的 <tab-bar></tab-bar> 组件 是我自定义的组件 可以删除 3. 代码中的图片地址以及视频地址请更换为自…

sed利用脚本处理文件

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

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

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

【Spring Framework】使用完全注解方式开发

Spring Framework 是一个非常灵活且强大的 Java 企业级开发框架&#xff0c;它允许开发人员以多种方式进行配置和开发。在现代 Java 开发中&#xff0c;使用完全注解的方式来进行配置和开发已经成为趋势&#xff0c;这种方式能够减少 XML 配置文件的使用&#xff0c;使代码更加…