深入研究查询Elasticsearch,过滤查询和全文搜索

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入研究查询Elasticsearch,过滤查询和全文搜索相关的知识,希望对你有一定的参考价值。

参考技术A

或如何了解缺少哪些官方文件

如果我不得不用一个短语来描述Elasticsearch,我会说:

目前,Elasticsearch在十大最受欢迎的开源技术中。 公平地说,它结合了许多本身并不独特的关键功能,但是,当结合使用时,它可以成为最佳的搜索引擎/分析平台。

更准确地说,由于以下功能的结合,Elasticsearch变得如此流行:

· 搜索相关性评分

· 全文搜索

· 分析(汇总)

· 无模式(对数据模式无限制),NoSQL,面向文档

· 丰富的数据类型选择

· 水平可扩展

· 容错的

通过与Elasticsearch进行合作,我很快意识到,官方文档看起来更像是所谓文档的"挤压"。 我不得不在Google上四处搜寻,并且大量使用stackowerflow,所以我决定编译这篇文章中的所有信息。

在本文中,我将主要撰写有关查询/搜索Elasticsearch集群的文章。 您可以通过多种不同的方式来实现大致相同的结果,因此,我将尝试说明每种方法的利弊。

更重要的是,我将向您介绍两个重要的概念-查询和过滤器上下文-在文档中没有很好地解释。 我将为您提供一组规则,以决定何时使用哪种方法更好。

在阅读本文后,如果我只想让您记住一件事,那就是:

当我们谈论Elasticsearch时,总会有一个相关性分数。 相关性分数是严格的正浮点数,表示每个文档满足搜索标准的程度。 该分数是相对于分配的最高分数的,因此,分数越高,文档与搜索条件的相关性越好。

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

一般来说,过滤器上下文是一个"是/否"选项,其中每个文档都与查询匹配或不匹配。 一个很好的例子是SQL WHERE,后面是一些条件。 SQL查询总是返回严格符合条件的行。 SQL查询无法返回歧义结果。

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

经验法则是将过滤器用于:

· 是/否搜索

· 搜索精确值(数字,范围和关键字)

将查询用于:

· 结果不明确(某些文档比其他文档更适合)

· 全文搜索

此外,Elasticsearch将自动缓存过滤器的结果。

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


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

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

名词查询 Term Query

返回字段值与条件完全匹配的文档。 查询一词是SQL select * from table_name where column_name =...的替代方式

名词查询直接进入倒排索引,这可以使其快速进行。 在处理文本数据时,最好仅将term用于keyword字段。


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

带有过滤条件的 名词 查询

如果我们想加速名词查询并使其得到缓存,则应将其包装在constant_score过滤器中。

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

现在,该查询没有计算任何相关性分数,因此,它更快。 而且,它是自动缓存的。

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

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

多名词查询 Terms query

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

多名词查询在某种程度上是SQL select * from table_name where column_name is in...的替代方法

重要的是要了解,Elasticsearch中的查询字段可能是一个列表,例如“ name”:[“ Odin”,“ Woden”,“ Wodan”]。如果您执行的术语查询包含以下一个或多个,则该记录将被匹配-它不必匹配字段中的所有值,而只匹配一个。


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

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

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

等价于SQL select * from table_name where column_name is between...

范围查询具有自己的语法:

· gt 大于

· gte 大于或等于

· lt 小于

· lte 小于或等于

一个示例,该字段的值应≥4且≤17


范围查询也可以很好地与日期配合使用。

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

如果您从未使用过正则表达式,那么我强烈建议您至少了解一下它是什么以及何时可以使用它。

Elasticsearch的正则表达式是Lucene的正则表达式。 它具有标准的保留字符和运算符。 如果您已经使用过Python的re软件包,那么在这里使用它应该不是问题。 唯一的区别是Lucene的引擎不支持^和$等锚运算符。

您可以在官方文档中找到regexp的完整列表。

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

不幸的是,我找不到关于这三个查询的性能的任何信息,因此,我决定自己对其进行测试,以查看是否发现任何重大差异。

在比较使用rehexp和通配符查询时,我找不到性能上的差异。如果您知道有什么不同,请给我发消息。

由于Elasticsearch是无模式的(或没有严格的模式限制),因此当不同的文档具有不同的字段时,这是一种很常见的情况。 结果,有很多用途来了解文档是否具有某些特定字段。


全文查询适用于非结构化文本数据。 全文查询利用了分析器。 因此,我将简要概述Elasticsearch的分析器,以便我们可以更好地分析全文查询。

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

分析器管道包括三个阶段:

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

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

· 替换与给定正则表达式匹配的字符

· 替换与给定字符串匹配的字符

· 干净的html文字

2)令牌生成器将字符过滤器(如果有)之后接收到的文本数据分解为令牌。 例如,空白令牌生成器只是将文本分隔为空白(这不是标准的)。 因此,Wednesday is called after Woden, 将被拆分为[Wednesday, is, called, after, Woden.]。 有许多内置标记器可用于创建自定义分析器。

删除标点符号后,标准令牌生成器将使用空格分隔文本。 对于绝大多数语言来说,这是最中立的选择。

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

· 跟踪令牌顺序,

· 注释每个单词的开头和结尾

· 定义令牌的类型

3)令牌过滤器对令牌进行一些转换。您可以选择将许多不同的令牌过滤器添加到分析器中。一些最受欢迎的是:

· 小写

· 词干(存在多种语言!)

· 删除重复

· 转换为等效的ASCII

· 模式的解决方法

· 令牌数量限制

· 令牌的停止列表(从停止列表中删除令牌)

标准分析器是默认分析器。 它具有0个字符过滤器,标准令牌生成器,小写字母和停止令牌过滤器。 您可以根据需要组成自定义分析器,但是内置分析器也很少。

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

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

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

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

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

当您指定要搜索的短语时,将对其进行分析,并且结果始终是一组标记。默认情况下,Elasticsearch将在所有这些标记之间使用OR运算符。这意味着至少应该有一场比赛-更多的比赛虽然会得分更高。您可以在运算符参数中将其切换为AND。在这种情况下,必须在文档中找到所有令牌才能将其返回。

如果要在OR和AND之间输入某些内容,则可以指定minimum_should_match参数,该参数指定应匹配的子句数。 可以数字和百分比指定。

模糊参数(可选)可让您忽略错别字。 Levenshtein距离用于计算。

如果您将匹配查询应用于关键字keyword字段,则其效果与词条查询相同。 更有趣的是,如果将存储在反向索引中的令牌的确切值传递给term查询,则它将返回与匹配查询完全相同的结果,但是会更快地返回到反向索引。

与匹配相同,但顺序和接近度很重要。 匹配查询不了解序列和接近度,因此,只有通过其他类型的查询才能实现词组匹配。

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

多重比对查询的功能与比对相同,唯一的不同是多重比对适用于多个栏位

· 字段名称可以使用通配符指定

· 默认情况下,每个字段均加权

· 每个领域对得分的贡献都可以提高

· 如果没有在fields参数中指定任何字段,那么将搜索所有符合条件的字段

有多种类型的multi_match。 我不会在这篇文章中描述它们,但是我将解释最受欢迎的:

best_fields类型(默认值)更喜欢在一个字段中找到来自搜索值的令牌的结果,而不是将搜索的令牌分配到不同字段中的结果。

most_fields与best_fields类型相反。

phrase类型的行为与best_fields相同,但会搜索与match_phrase类似的整个短语。

我强烈建议您查阅官方文档,以检查每个字段的得分计算准确度。

复合查询将其他查询包装在一起。 复合查询:

· 结合分数

· 改变包装查询的行为

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

· 以上任意一项

布尔查询将其他查询组合在一起。 这是最重要的复合查询。

布尔查询使您可以将查询上下文中的搜索与过滤器上下文搜索结合在一起。

布尔查询具有四个可以组合在一起的出现(类型):

· must或"必须满足该条款"

· should或"如果满足条款,则对相关性得分加分"

· 过滤器filter或"必须满足该条款,但不计算相关性得分"

· must_not或“与必须相反”,不会有助于相关度得分

必须和应该→查询上下文

过滤器和must_not→过滤器上下文

对于那些熟悉SQL的人,必须为AND,而应为OR运算符。 因此,必须满足must子句中的每个查询。

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

如我们在术语查询示例中先前看到的,constant_score查询将任何查询转换为相关性得分等于boost参数(默认值为1)的过滤器上下文。


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

我计划在Elasticsearch上发布更多文章,所以不要错过。

你已经读了很长的内容,所以如果你阅读到这里:

综上所述,Elasticsearch符合当今的许多用途,有时很难理解什么是最佳工具。

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

另外,了解Elasticsearch的工作原理也至关重要,因此,我建议您始终了解分析器的功能。

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

(本文翻译自kotartemiy ✔️的文章《Deep Dive into Querying Elasticsearch. Filter vs Query. Full-text search》,参考:https://towardsdatascience.com/deep-pe-into-querying-elasticsearch-filter-vs-query-full-text-search-b861b06bd4c0)

Elasticsearch 查询与过滤

 

今天在给上级汇报工作的时候,被问到了这个问题,一时也没回到上来。

英文原文:

https://www.elastic.co/guide/en/elasticsearch/guide/current/_queries_and_filters.html

 

前面我们讲到的是关于结构化查询语句,事实上我们可以使用两种结构化语句: 结构化查询(Query DSL)和结构化过滤(Filter DSL)。 查询与过滤语句非常相似,但是它们由于使用目的不同而稍有差异。

一条过滤语句会询问每个文档的字段值是否包含着特定值:

  • created 的日期范围是否在 20132014 ?
  • status 字段中是否包含单词 "published" ?
  • lat_lon 字段中的地理位置与目标点相距是否不超过10km ?

一条查询语句与过滤语句相似,但问法不同:

查询语句会询问每个文档的字段值与特定值的匹配程度如何?

查询语句的典型用法是为了找到文档:

  • 查找与 full text search 这个词语最佳匹配的文档
  • 查找包含单词 run ,但是也包含runs, running, jogsprint的文档
  • 同时包含着 quick, brownfox --- 单词间离得越近,该文档的相关性越高
  • 标识着 lucene, searchjava --- 标识词越多,该文档的相关性越高

一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score,并且 按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。

性能差异

使用过滤语句得到的结果集 -- 一个简单的文档列表,快速匹配运算并存入内存是十分方便的, 每个文档仅需要1个字节。这些缓存的过滤结果集与后续请求的结合使用是非常高效的。

查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存。

幸亏有了倒排索引,一个只匹配少量文档的简单查询语句在百万级文档中的查询效率会与一条经过缓存 的过滤语句旗鼓相当,甚至略占上风。 但是一般情况下,一条经过缓存的过滤查询要远胜一条查询语句的执行效率。

过滤语句的目的就是缩小匹配的文档结果集,所以需要仔细检查过滤条件。

什么情况下使用

原则上来说,使用查询语句做全文本搜索或其他需要进行相关性评分的时候,剩下的全部用过滤语句。

 

以上是关于深入研究查询Elasticsearch,过滤查询和全文搜索的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch:深入理解 Elasticsearch 查询:过滤器查询 vs 全文搜索

Elasticsearch:深入理解 Elasticsearch 查询:过滤器查询 vs 全文搜索

elasticsearch基本查询笔记(三)-- es查询总结

elasticsearch 查询与过滤

Elasticsearch查询类型

Elasticsearch 查询与过滤