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

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

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

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

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

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

NOTE

自Elasticsearch问世以来,查询与过滤(queries and filters)就独自称为Elasticsearch的组件。但从Elasticsearch2.0 开始,过滤(filters)已经从技术上被排除了,同时所有的查询(queries)拥有变成不评分查询的能力。

然而,为了明确和简单,我们用“filter”这个词表示不评分、只过滤情况下的查询。你可以把“filter”、“filtering query”和“non-scoring query”这几个词视为相同的。

相似的,如果单独的不加任何修饰词的使用“query”这个词,我们指的是“scoring query”。

性能差异

过滤查询(Filtering queries)只是简单的检查包含或者排除,这就使得计算起来非常快。考虑到至少有一个过滤查询(filtering query)的结果是“稀少的”(很少匹配的文档),并且经常使用不评分查询(non-scoring queries),结果会被缓存到内存中以便快速读取,所以有各种各样的手段来优化查询结果。

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

多亏倒排索引(inverted index),一个简单的评分查询在匹配少量文档时可能与一个涵盖百万文档的filter表现的一样好,甚至会更好。但是在一般情况下,一个filter会比一个评分的query性能更优异,并且每次都表现的很稳定。

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

如何选择查询与过滤

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