现实的查询需求从来都没有那么简单;他们需要在多个字段上查询多种多样的文本,并且根据一系列的标准来过滤。为了构建类似的高级查询,你需要一种能够将多查询组合成单一查询的查询方法。

你可以用bool 查询来实现你的需求。这种查询将多查询组合在一起,成为用户自己想要的布尔查询。他接收以下参数:

must

文档必须匹配这些条件才能被包含进来。

must_not

文档必须不匹配这些条件才能被包含进来

should

如果满足这些语句中的任意语句,将增加_source,否则,无任何影响。他们主要用于修正每个文档的相关性得分。

filter

必须匹配,但他以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

由于这是我们看到的第一个包含多个查询的查询,所以有必要讨论一下相关性得分是如何组合的。每一个子查询都独自的计算文档的相关性得分。一旦他们的得分被计算出来,bool 查询就将这些得分进行合并并且返回一个代表整个布尔操作的得分。

下面的查询用于查找title 字段匹配 how ti make millions 并且不被标识为spam 的文档。那些被标识为starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。如果两者 都满足,那么他排名将更高:

  1. {
  2. "bool": {
  3. "must": { "match": { "title": "how to make millions" }},
  4. "must_not": { "match": { "tag": "spam" }},
  5. "should": [
  6. { "match": { "tag": "starred" }},
  7. { "range": { "date": { "gte": "2014-01-01" }}}
  8. ]
  9. }
  10. }

TIP

如果没有must 语句,那么至少需要能够匹配其中的一条 should语句。但,如果存在至少一条must 语句,则对 should 语句的匹配没有要求。

增加带过滤器(filtering)的查询

如果我们不想因为文档的时间而影响得分,可以用 filter 语句来重写前面的例子;

  1. {
  2. "bool": {
  3. "must": { "match": { "title": "how to make millions" }},
  4. "must_not": { "match": { "tag": "spam" }},
  5. "should": [
  6. { "match": { "tag": "starred" }}
  7. ],
  8. "filter": {
  9. "range": { "date": { "gte": "2014-01-01" }} 1
  10. }
  11. }
  12. }
  1. range 查询已经从 should 语句中移到filter 语句

通过将range 查询移到 filter 语句中,我们将它转成不评分的查询,将不再影响文档的相关性排名。由于他现在是一个不评分的查询,可以使用各种对 filter 查询有效的优化手段来提升性能。

所有查询都可以借鉴这种方式。将查询移到bool 查询的filter 语句中,这样他就自动的转成一个不评分的filter 了。

如果你需要通过多个不同标准来过滤你的文档,bool 查询本身也可以被用做不评分的查询。简单的将它放置到filter 语句中并在内部构建布尔逻辑:

  1. {
  2. "bool": {
  3. "must": { "match": { "title": "how to make millions" }},
  4. "must_not": { "match": { "tag": "spam" }},
  5. "should": [
  6. { "match": { "tag": "starred" }}
  7. ],
  8. "filter": {
  9. "bool": { 1
  10. "must": [
  11. { "range": { "date": { "gte": "2014-01-01" }}},
  12. { "range": { "price": { "lte": 29.99 }}}
  13. ],
  14. "must_not": [
  15. { "term": { "category": "ebooks" }}
  16. ]
  17. }
  18. }
  19. }
  20. }
  1. 将bool 查询包裹在filter 语句中,我们可以在过滤标准中增加布尔逻辑。

通过混合布尔查询,我们可以在我们的查询请求中灵活的编写scoring 和filtering 查询逻辑。

constant_score查询

尽管没有bool 查询使用这么频繁,constant_score 查询也是你工具箱里有用的查询工具。他将一个不变的常量评分应用于所有匹配的文档。他被经常用于你只需要执行一个filter 而没有其他查询(例如,评分查询)的情况下。

可以使用他来取代只有filter 语句的bool查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。

  1. {
  2. "constant_score": {
  3. "filter": {
  4. "term": { "category": "ebooks" } 1
  5. }
  6. }
  7. }
  1. term 查询被放置在constant_score 中,转成不评分的filter。这种方式可以用来取代只有filter 语句的bool 查询。