组合查询

在《组合过滤》中我们讨论了怎样用布尔过滤器组合多个用and, or, and not逻辑组成的过滤子句,在查询中, 布尔查询充当着相似的作用,但是有一个重要的区别。

过滤器会做一个判断: 是否应该将文档添加到结果集? 然而查询会做更精细的判断. 他们不仅决定一个文档是否要添加到结果集,而且还要计算文档的相关性(relevant).

像过滤器一样, 布尔查询接受多个用must, must_not, and should的查询子句. 例:

  1. GET /my_index/my_type/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": { "match": { "title": "quick" }},
  6. "must_not": { "match": { "title": "lazy" }},
  7. "should": [
  8. { "match": { "title": "brown" }},
  9. { "match": { "title": "dog" }}
  10. ]
  11. }
  12. }
  13. }

在前面的查询中,凡是满足title字段中包含quick,但是不包含lazy的文档都会在查询结果中。到目前为止,布尔查询的作用非常类似于布尔过滤的作用。

should过滤器中有两个子句时不同的地方就体现出来了,下面例子就可以体现:一个文档不需要同时包含browndog,但如果同时有这两个词,这个文档的相关性就更高:

  1. {
  2. "hits": [
  3. {
  4. "_id": "3",
  5. "_score": 0.70134366, <1>
  6. "_source": {
  7. "title": "The quick brown fox jumps over the quick dog"
  8. }
  9. },
  10. {
  11. "_id": "1",
  12. "_score": 0.3312608,
  13. "_source": {
  14. "title": "The quick brown fox"
  15. }
  16. }
  17. ]
  18. }

<1> 文档3的得分更高,是因为它同时包含了browndog

得分计算

布尔查询通过把所有符合mustshould的子句得分加起来,然后除以mustshould子句的总数为每个文档计算相关性得分。

must_not子句并不影响得分;他们存在的意义是排除已经被包含的文档。

精度控制

所有的 must 子句必须匹配, 并且所有的 must_not 子句必须不匹配, 但是多少 should 子句应该匹配呢? 默认的,不需要匹配任何 should 子句,一种情况例外:如果没有must子句,就必须至少匹配一个should子句。

像我们控制match查询的精度一样,我们也可以通过minimum_should_match参数控制多少should子句需要被匹配,这个参数可以是正整数,也可以是百分比。

  1. GET /my_index/my_type/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "should": [
  6. { "match": { "title": "brown" }},
  7. { "match": { "title": "fox" }},
  8. { "match": { "title": "dog" }}
  9. ],
  10. "minimum_should_match": 2 <1>
  11. }
  12. }
  13. }

<1> 这也可以用百分比表示

结果集仅包含title字段中有"brown" 和 "fox", "brown" 和 "dog", 或 "fox" 和 "dog"的文档。如果一个文档包含上述三个条件,那么它的相关性就会比其他仅包含三者中的两个条件的文档要高。