ES查询与过滤对比

  • Post author:
  • Post category:其他




查询与过滤

Elasticsearch 使用的查询语言(DSL)拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。这套组件可以在以下两种情况下使用:

过滤情况(filtering context)和查询情况(query context)。

当使用于 过滤情况 时,查询被设置成一个“不评分”或者“过滤”查询。即,这个查询只是简单的问一个问题:“这篇文档是否匹配?”。回答也是非常的简单,yes 或者 no ,二者必居其一。

  • created 时间是否在 2013 与 2014 这个区间?
  • status 字段是否包含 published 这个单词?
  • lat_lon 字段表示的位置是否在指定点的 10km 范围内?

当使用于 查询情况 时,查询就变成了一个“评分”的查询。和不评分的查询类似,也要去判断这个文档是否匹配,同时它还需要判断这个文档匹配的有 多好(匹配程度如何)。 此查询的典型用法是用于查找以下文档:

  • 查找与 full text search 这个词语最佳匹配的文档
  • 包含 run 这个词,也能匹配 runs 、 running 、 jog 或者 sprint
  • 包含 quick 、 brown 和 fox 这几个词 — 词之间离的越近,文档相关性越高
  • 标有 lucene 、 search 或者 java 标签 — 标签越多,相关性越高

一个评分查询计算每一个文档与此查询的 相关程度,同时将这个相关程度分配给表示相关性的字段 _score,并且按照相关性对匹配到的文档进行排序。这种相关性的概念是非常适合全文搜索的情况,因为全文搜索几乎没有完全 “正确” 的答案。

举例:

以下是在搜索API的查询和过滤器中使用的查询子句的示例。 此查询将匹配满足以下所有条件的文档:

GET /_search
{
  "query": { 
    "bool": { 
      "must": [
        { "match": { "title":   "Search"        }},
        { "match": { "content": "Elasticsearch" }}
      ],
      "filter": [ 
        { "term":  { "status": "published" }},
        { "range": { "publish_date": { "gte": "2015-01-01" }}}
      ]
    }
  }
}

  • query

    参数指示查询内容

  • bool

    和两个

    match

    子句在查询内容中使用,这意味着它们用于对每个文档的匹配程度进行评分。

  • filter

    参数指示过滤器内容。 它的

    term



    range

    子句用于过滤器上下文。 它们将过滤出不匹配的文档,但不会影响匹配文档的分数。



性能差异

过滤查询(Filtering queries)只是简单的检查包含或者排除,这就使得计算起来非常快。考虑到至少有一个过滤查询(filtering query)的结果是 “稀少的”(很少匹配的文档),并且经常使用不评分查询(non-scoring queries),

结果会被缓存到内存中以便快速读取

,所以有各种各样的手段来优化查询结果。

相反,评分查询(scoring queries)不仅仅要找出匹配的文档,还要计算每个匹配文档的相关性,计算相关性使得它们比不评分查询费力的多。同时,查询结果并不缓存。

多亏倒排索引(inverted index),一个简单的评分查询在匹配少量文档时可能与一个涵盖百万文档的filter表现的一样好,甚至会更好。

但是在一般情况下,一个filter 会比一个评分的query性能更优异,并且每次都表现的很稳定

过滤(filtering)的目标是减少那些需要通过评分查询(scoring queries)进行检查的文档。



如何选择查询与过滤


通常的规则是,使用查询(query)语句来进行 全文 搜索或者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使用过滤(filters)



版权声明:本文为weixin_38932035原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。