查询与过滤器
Posted
技术标签:
【中文标题】查询与过滤器【英文标题】:Queries vs. Filters 【发布时间】:2013-01-13 19:05:47 【问题描述】:我看不到关于何时应该使用查询或过滤器或两者的某种组合的任何描述。它们之间有什么区别?谁能解释一下?
【问题讨论】:
官方文档其实不是很清楚 好像出现了一个解释更高级的页面:elastic.co/guide/en/elasticsearch/guide/master/… 值得注意的是 queries and filters will be merged 在 ES 2.0 中,因此大部分针对查询和过滤器所说和编写的内容将不再适用。另请查看宣布此更改的official blog post。 【参考方案1】:区别很简单:过滤器被缓存并且不影响分数,因此比查询更快。也看看here。假设查询通常是用户键入的并且几乎不可预测的内容,而过滤器帮助用户缩小搜索结果的范围,例如使用方面。
【讨论】:
对了,如果用户在进行 google 类型搜索,那么我会使用查询吗?如果他们从下拉列表中选择可能的值(例如,发票数量 > 50),那么这将是一个过滤器? 是的,完全正确。任何时候您需要通过某个度量来限制整个文档集,这通常是适合使用过滤器的情况。所以可能是年龄、长度、大小等 我的解决方案在同一个请求中使用过滤器和查询,并且在测试数据库上速度非常快。我们很快就会得到实时数据,看看它到底有多快。 @Zach 绝对清楚,在多租户系统中——租户内的用户具有权限——听起来租户/身份验证信息将是添加到每个查询的过滤器(即过滤查询)。对吗? @activescott 是的,这就是我要做的。您还可以设置过滤别名,以便“用户别名”始终应用适当的过滤器。使管理更容易,并且不需要更改代码来更新查询、查询中的额外内容等。【参考方案2】:这是官方文档所说的:
作为一般规则,应该使用过滤器而不是查询:
用于二进制是/否搜索 查询确切值
作为一般规则,应使用查询而不是过滤器:
用于全文搜索 结果取决于相关性分数
【讨论】:
当我想删除文档时,是否应该尽可能使用过滤器?我不希望它被缓存 删除文档时,不需要任何分数,也不需要进行全文搜索。所以这将是一个过滤器,因为您只需要做出删除/不删除决定。 filter-query-context【参考方案3】:一个例子(自己试试)
说索引myindex
包含三个文档:
curl -XPOST localhost:9200/myindex/mytype -d ' "msg": "Hello world!" '
curl -XPOST localhost:9200/myindex/mytype -d ' "msg": "Hello world! I am Sam." '
curl -XPOST localhost:9200/myindex/mytype -d ' "msg": "Hi Stack Overflow!" '
查询:文档与查询的匹配程度
查询hello sam
(使用关键字must
)
curl localhost:9200/myindex/_search?pretty -d '
"query": "bool": "must": "match": "msg": "hello sam"
'
文档"Hello world! I am Sam."
的得分高于"Hello world!"
,因为前者匹配查询中的两个词。 对文档进行评分。
"hits" : [
...
"_score" : 0.74487394,
"_source" :
"name" : "Hello world! I am Sam."
...
"_score" : 0.22108285,
"_source" :
"name" : "Hello world!"
...
过滤器:文档是否匹配查询
过滤hello sam
(使用关键字filter
)
curl localhost:9200/myindex/_search?pretty -d '
"query": "bool": "filter": "match": "msg": "hello sam"
'
返回包含hello
或sam
的文档。 文档不计分。
"hits" : [
...
"_score" : 0.0,
"_source" :
"name" : "Hello world!"
...
"_score" : 0.0,
"_source" :
"name" : "Hello world! I am Sam."
...
除非您需要全文搜索或评分,否则首选过滤器,因为 Elasticsearch 会自动缓存经常使用的过滤器,以提高性能。见Elasticsearch: Query and filter context.
【讨论】:
【参考方案4】:Filters
-> 这个文件匹配吗?二进制是或否答案
Queries
-> 这个文件匹配吗?匹配程度如何?使用评分
【讨论】:
【参考方案5】:除此之外几乎没有其他内容。 首先应用过滤器,然后根据其结果处理查询。为了存储每个文档的二进制真/假匹配,使用了一个叫做 bitSet Array 的东西。 这个 BitSet 数组在内存中,它将在第二次查询过滤器时使用。这样,使用 bitset 数组数据结构,我们就可以利用缓存的结果。
这里还有一点要注意,过滤器缓存仅在请求执行时创建,因此仅从第二次命中开始,我们实际上获得了缓存的优势。
但是你可以使用 warmer API 来超越它。当您使用过滤器针对更温暖的 API 注册查询时,它将确保在新段上线时执行此操作。因此,我们将从第一次执行本身获得一致的速度。
【讨论】:
有趣!我没有意识到过滤器发生在查询之前。过滤器的缓存现在更有意义了。 并非总是如此。过滤和恒定分数查询之间的基本和主要区别。常数分数总是先执行查询,然后对其应用过滤器。即使是过滤后的查询也有设置,查询可以在过滤器之前执行。【参考方案6】:基本上,当您想要对带有评分的文档执行搜索时,会使用查询。 过滤器用于缩小使用查询获得的结果集。过滤器是布尔值。
例如,假设您有一个餐厅索引,例如 zomato。 现在您要搜索提供'pizza'的餐厅,这基本上是您的搜索关键字。
所以你将使用查询来查找所有包含“pizza”的文档,并会得到一些结果。
现在说您想要提供比萨饼且评分至少为 4.0 的餐厅列表。
因此,您需要做的是在查询中使用关键字“pizza”,并应用过滤器以将评分设为 4.0。
发生的情况是过滤器通常应用于通过查询索引获得的结果。
【讨论】:
你不能提供一个请求正文的例子吗?【参考方案7】:自 Elasticsearch 第 2 版以来,过滤器和查询已合并,任何查询子句都可以用作过滤器或查询(取决于上下文)。与版本 1 一样,过滤器被缓存,如果评分无关紧要,则应使用过滤器。
来源:https://logz.io/blog/elasticsearch-queries/
【讨论】:
【参考方案8】:查询:计算分数;因此他们能够返回按相关性排序的结果。 过滤器:不计算分数,使它们更快更容易缓存。
【讨论】:
以上是关于查询与过滤器的主要内容,如果未能解决你的问题,请参考以下文章
Graphene/Django (GraphQL):如何使用查询参数来排除与特定过滤器匹配的节点?