我看不到任何关于何时应该使用查询或过滤器或两者的组合的描述。它们之间有什么区别?谁能解释一下吗?
区别很简单:过滤器被缓存并且不影响分数,因此比查询更快。也看看这里。假设查询通常是用户输入的内容,并且几乎是不可预测的,而过滤器可以帮助用户缩小搜索结果范围,例如使用方面。
官方文档是这么说的:
作为一般规则,应使用过滤器而不是查询:
- 用于二元是/否搜索
- 查询精确值
作为一般规则,应使用查询而不是过滤器:
- 用于全文搜索
- 结果取决于相关性分数
假设索引
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."
}
...
Filters
-> 该文档匹配吗?二进制是或否答案
Queries
-> 该文档匹配吗?匹配得怎么样?使用评分
还有一些其他的东西。 首先应用过滤器,然后根据其结果处理查询。为了存储每个文档的二进制真/假匹配,使用了称为 bitSet 数组的东西。 该 BitSet 数组位于内存中,并且将从第二次查询过滤器时使用该数组。这样,使用位集数组数据结构,我们就可以利用缓存的结果。
这里还有一点需要注意,过滤器缓存仅在请求执行时创建,因此仅从第二次命中开始,我们实际上获得了缓存的优势。
但是你可以使用 更温暖的 API 来解决这个问题。当您使用针对较温暖的 API 的过滤器注册查询时,它将确保每当新段上线时都会针对新段执行该查询。因此,我们将从第一次执行本身获得一致的速度。
基本上,当您想要通过评分对文档执行搜索时,会使用查询。 过滤器用于缩小通过查询获得的结果集的范围。过滤器是布尔值。
例如,假设您有一个类似 zomato 的餐厅索引。 现在您想要搜索提供 'pizza' 的餐厅,这基本上就是您的搜索关键字。
因此,您将使用查询来查找所有包含 “pizza” 的文档,并将获得一些结果。
现在假设您想要提供披萨且评分至少为 4.0 的餐厅列表。
因此,您要做的就是在查询中使用关键字 “pizza” 并应用过滤器将评级设置为 4.0。
发生的情况是,过滤器通常应用于通过查询索引获得的结果。
从 Elasticsearch 版本 2 开始,过滤器和查询已合并,任何查询子句都可以用作过滤器或查询(取决于上下文)。与版本 1 一样,过滤器会被缓存,如果评分不重要,则应使用过滤器。
查询:计算分数;因此他们能够返回按相关性排序的结果。 过滤器:不计算分数,使它们更快更容易缓存。