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