深入研究查询弹性搜索、过滤查询和全文搜索

< p >或者如何知道哪些官方文件丢失了

怎么查询公司

< p >埃胡德·纽豪斯在Unsplash

上的照片

如果我必须用一个短语来描述弹性搜索,我会说

搜索遇到大规模(近实时)分析

目前,弹性搜索是十大最流行的开源技术之一公平地说,它结合了许多本身并不独特的关键功能,但如果结合使用,它可以成为最好的搜索引擎/分析平台。

更准确地说,由于结合了以下功能,弹性搜索变得如此流行:

,搜索相关性得分

,全文搜索

、分析(总结)

。无模式(对数据模式没有限制),NoSQL,面向文档的

。对于丰富的数据类型,选择

。级别可扩展

,容错

通过与弹性搜索的合作,我很快意识到正式文件看起来更像是所谓的“挤压”文件。我不得不在谷歌上搜索,并广泛使用stackowerflow,所以我决定将本文中的所有信息进行汇总。

在本文中,我将主要写关于查询/搜索弹性搜索集群的文章。你可以用许多不同的方法获得大致相同的结果,所以我将试着解释每种方法的优缺点。

更重要的是,我将向您介绍两个重要的概念——查询和过滤器上下文——这两个概念在文档中没有得到很好的解释。我会给你一套规则来决定什么时候哪种方法更好。

读完这篇文章,如果我只想让你记住一件事,那就是:

查询时

真的需要对文档评分吗?

查询上下文和过滤器上下文

当我们谈论弹性搜索时,总是有一个相关得分相关性分数是一个严格的正浮点数,表示每个文档满足搜索标准的程度。分数与指定的最高分数相关,因此分数越高,文档与搜索标准的相关性就越好。

但是,过滤器和查询是两个不同的概念,在编写查询之前您应该能够理解它们

一般来说,过滤器上下文是“是/否”选项,其中每个文档与查询匹配或不匹配一个很好的例子是SQL WHERE,后跟一些条件SQL查询总是返回严格限定的行SQL查询不能返回不明确的结果

过滤器将被自动缓存,无助于相关性评分。

另一方面,弹性搜索查询上下文显示了每个文档与您的需求的匹配程度。为此,查询使用分析器来找到最佳匹配

的经验法则是:

使用过滤器

。是/否搜索

。搜索精确值(数字、范围和关键字)

使用查询:

。模棱两可的结果(有些文件比其他文件更合适)

,全文搜索

总是尝试使用过滤器,除非您需要相关性分数或全文搜索过滤器“便宜”

此外,弹性搜索将自动缓存过滤器的结果

在第1部分和第2部分中,我将讨论查询(可以转换为过滤器)请不要将结构化和全文与查询和过滤器混淆——这是两件事。

1.结构化查询

结构化查询,也称为术语级查询,是一组用于检查是否应该选择文档的查询方法。因此,在许多情况下,没有真正必要的相关性分数——文档匹配或不匹配(尤其是数字)

术语级查询仍然是查询,因此它们将返回分数

名词查询术语查询

返回其字段值与标准完全匹配的文档查询一词是从表名中选择*的替代词,其中列名=...

名词查询直接进入倒排索引,这可以使它更快处理文本数据时,最好只对关键字字段使用术语

GET /_search{ "查询":{ "术语":{ " ":{ "值": " " } } }} 默认情况下,

名词查询在查询上下文中运行,因此它会计算分数即使所有返回文档的分数相同,也会涉及其他计算能力。

带过滤器

名词查询

如果我们想要加速名词查询并缓存它们,我们应该将它们包装在常量分数过滤器中。

记得经验法则吗?如果您不关心相关性分数,请使用此方法

GET/_ search { " query ":{ " constant _ score ":{ " filter ":{ " term ":{ " " : " " } } } }}

现在,查询不计算任何相关分数,因此速度更快此外,它是自动缓存的

快速建议-文本字段使用匹配而不是名词

请记住名词查询直接进入倒排索引名词查询采用您提供的值,并按原样进行搜索,这就是为什么它非常适合于查询未经任何转换而存储的关键字字段。

多名词查询术语sqr

如您所料,多名词查询使您能够返回至少匹配一个确切名词的文档

多名词查询在某种程度上是从表名中选择*的另一种方法

column _ name在其中...

请务必理解,弹性搜索中的查询字段可能是一个列表,如{“名称”:[“奥丁”、“沃顿”、“沃丹”]}如果您执行的术语查询包含以下一项或多项,则记录将被匹配-它不必匹配字段中的所有值,而只匹配一项

GET/_ search { " query ":{ " terms ":{ " name ":["弗丽嘉"、"奥丁"、"巴德尔"] } }}

名词集查询

与名词查询相同,但是这次您可以在查询字段中指定多少个确切的术语?

您指定了必须匹配的数量-1、2、3或全部但是,这个数字是另一个数字字段因此,每个文档都应该包含编号(特定于该特定文档)

范围查询

返回查询字段值在定义范围内的文档

等效于SQL select * from table _ name,其中column _ nameis介于...

范围查询有自己的语法:

.gt >

GTE大于或等于

.lt小于

LTE小于或等于

为例,此字段的值应≥4且≤17

GET _search{ "查询":{ "范围":{ " ":{“GTE”:4,“LTE”:17 } } }

范围查询也可以很好地用于日期。

正则表达式、通配符和前缀查询

正则表达式查询返回字段与正则表达式匹配的文档

如果您从未使用过正则表达式,我强烈建议您至少知道它是什么以及何时可以使用它

弹性搜索的正则表达式是Lucene的正则表达式。它有标准的保留字符和运算符如果您已经使用了Python的re软件包,那么在这里使用它应该不成问题。唯一的区别是Lucene的引擎不支持像和$这样的锚操作符

您可以在官方文件中找到正则表达式的完整列表

除了正则表达式查询之外,Elsticsearch还具有通配符和前缀查询从逻辑上讲,这两个只是正则表达式的特例

不幸的是,我找不到关于这三个查询性能的任何信息,所以我决定自己测试它们,看看是否发现了任何显著的差异。

在比较使用重复表达式和通配符的查询时,我找不到任何性能差异。如果你知道有什么不同,请给我发个信息。

有一个问题

因为弹性搜索是非模态的(或者没有严格的模式限制),当不同的文档有不同的字段时,这是非常常见的情况。因此,知道文档是否有特定字段有许多用途。

查询存在返回文档

包含字段索引值 GET /_search{ "查询":{ "存在":{ "字段": " " } }}

2.全文查询

非结构化文本数据的全文查询全文查询利用分析器因此,我将简要概述弹性搜索的分析器,以便我们能够更好地分析全文查询。

用于弹性研究的分析器管道

每次将文本类型数据插入弹性搜索索引时都会对其进行分析,并将其存储在反向索引中根据分析器的配置,这将影响您的搜索功能,因为分析器也适合全文搜索。

分析仪管道由三个阶段组成:

字符过滤器(0+)→令牌生成器(1)→令牌过滤器(0+)

总是有一个令牌生成器、零个或多个字符和令牌过滤器

1)字符过滤器按原样接收文本数据,然后在标记之前对数据进行预处理字符过滤器:

。替换与给定正则表达式匹配的256个以上的字符

。替换与给定字符串匹配的256个以上的字符

。清除超文本标记语言文本

2)标记生成器将字符过滤器(如果有的话)之后接收的文本数据分解成标记例如,空白标记生成器只是将文本分成空白(这不是标准)因此,星期三被称为以后,沃顿将被分割成[星期三,被称为,以后,沃顿。]有许多内置标记可用于创建自定义分析器

当标点符号被删除时,标准标记生成器用空格分隔文本对于大多数语言来说,这是最中性的选择。

除了标记,标记器还执行以下操作:

,跟踪令牌订单,

。评论每个单词的开头和结尾

。定义令牌类型

3)令牌过滤器对令牌执行一些转换您可以选择向分析器添加许多不同的令牌过滤器一些最流行的是:

,小写

干(有多种语言!)

,删除重复的

...转换为等效的ASCII

。模式

的分辨率

,令牌限制

。令牌阻止列表(从阻止列表中删除令牌)

现在,当我们知道分析器由什么组成时,我们可以考虑如何处理数据。然后,我们可以通过选择合适的组件来形成最适合我们情况的分析器。可以在每个字段的基础上指定分析仪

已经谈论了足够多的理论。让我们看看默认分析器是如何工作的。

标准分析仪是默认分析仪它有一个0字符过滤器、一个标准令牌生成器、小写字母和一个停止令牌过滤器您可以根据需要编写定制的分析器,但是内置的分析器很少。

语言分析器是一些最有效的现成分析器,它们使用每种语言的细节进行更高级别的转换。因此,如果您事先知道数据的语言,建议您从标准分析器切换到数据语言。

全文查询将使用索引数据时使用的相同解析器更准确地说,您查询的文本将经历与搜索字段中的文本数据相同的转换,因此两者处于同一级别。

匹配查询

匹配查询是查询文本字段的标准查询

我们可以将匹配查询称为名词查询的等效查询,但它适用于文本类型字段(而名词仅应在处理文本数据时用于关键字类型字段)

GET /_search{ "查询":{ "匹配":{ " " { "查询" : " " } } }}

默认情况下,传递给查询参数(必需的参数)的字符串将由应用于搜索字段的解析器处理除非您自己使用分析仪参数指定分析仪

当您指定要搜索的短语时,会对其进行分析,结果总是一组标记默认情况下,弹性搜索在所有这些标签之间使用或运算符这意味着至少应该有一场比赛——越多的比赛得分越高您可以在运算符参数中将其切换为“与”在这种情况下,必须在要返回的文档中找到所有标记。

如果要输入或与之间的内容,可以指定minimum_should_match参数,该参数指定应该匹配的子句数可以用数字和百分比来表示

模糊参数(可选)允许您忽略打字错误Levenshtein距离用于计算

如果将匹配查询应用于关键字字段,它将具有与条目查询相同的效果更有趣的是,如果存储在反向索引中的令牌的确切值被传递给术语查询,它将返回与匹配查询完全相同的结果,但是返回到反向索引的速度会更快。

匹配短语查询

与匹配相同,但顺序和接近度很重要。匹配查询不知道顺序和邻近,因此,短语匹配只能通过其他类型的查询来实现。

GET /_search{ "查询":{ "匹配短语":{ " ":{ "查询" : " “,”污水“:“0”} } } }

匹配短语查询有一个slop参数(默认值为0),它负责跳过术语因此,如果指定斜率等于1,短语中可能会省略一个单词

多重比较查询

多重匹配查询的功能与匹配相同,只是多重匹配适用于多个字段

GET /_search{ "查询":{ "多重匹配":{ "查询": " ”,“领域”:[” “,” "] } }

...字段名可以使用通配符来指定

。默认情况下,每个字段的权重为

。每个字段对分数的贡献可以增加

。如果在字段参数中没有指定字段,将搜索所有符合条件的字段

有多种类型的多重匹配我不会在本文中描述它们,但我会解释最流行的:

best _ fields type(默认)更喜欢从一个字段的搜索值中查找标记的结果,而不是将搜索到的标记分配给不同字段的结果

most _ fields与best _ fields的类型相反

短语类型的行为与最佳字段相同,但会搜索与匹配短语相似的整个短语

我强烈建议您查阅官方文件,以检查每个字段的分数计算的准确性

3.复合查询

复合查询包装其他查询复合查询:

,综合得分

、改变打包查询行为

。将查询上下文切换到过滤上下文

,高于任何

布尔查询

布尔查询组合其他查询这是最重要的复合查询

布尔查询使您能够将查询上下文中的搜索与过滤器上下文搜索相结合

布尔查询有四个可以组合在一起的匹配项(类型):

mustor "必须符合本条款"

应该或“如果满足条件,将添加相关性分数”

。过滤过滤器或“必须满足此子句,但不计算相关分数”

的值。" |

must_not或“与必要性相反”不会对

的相关分数有所贡献

必须和应该→查询上下文

过滤且不得→过滤上下文

对于熟悉SQL的人来说,

必须是AND,而不是or运算符因此,必须满足must子句中的每个查询

促销查询

对于大多数查询,提升的查询与提升参数相似,但不同增强的查询将返回匹配肯定子句的文档,并降低匹配否定子句的文档的分数。

常量分数查询

正如我们在前面的术语查询示例中看到的,constant_score查询将任何查询转换为关联分数等于boost参数(默认值为1)的筛选器上下文

让我知道您是否想阅读另一篇提供所有查询的真实示例的文章。

我计划在弹性搜索上发表更多文章,所以不要错过

你已经读了很多,所以如果你在这里读:

总而言之,弹性搜索现在适用于许多用途,有时很难理解什么是最好的工具。

如果不需要相关性分数来检索数据,请尝试切换到筛选器上下文

了解弹性搜索的工作原理也很重要,因此我建议您始终了解分析仪的功能。

弹性搜索中还有许多其他查询类型。我试图描述最常用的我希望你喜欢它

(本文翻译自kotartemiy的文章“深入查询弹性搜索.过滤器vs查询.全文搜索”,参考:https://towardsdata science . com/deep-deep-深入查询-弹性搜索-过滤器-vs查询-全文搜索-b861b06bd4c0)

大家都在看

相关专题