Elasticsearch 中 must, filter, should, must_not, constant_score 的区别

10,394 阅读2分钟

先列举一下使用语法示例:

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

Bool Query

bool query 支持多种查询子句类型,分别是:

  • must:其查询子句必须全部被满足,逻辑相当于 and ,并且会计算分数。

  • filter:与 must 作用一样,但是不会计算分数。在 filter context 下的查询子句不会计算分数且会被缓存。

  • should:其查询子句应该被满足,也就是不一定都满足,逻辑相当于 or。

    • 如果 bool query 是在 query context 下,且包含 must 子句或 filter 子句,此时只要满足 must 子句或 filter 子句里的条件就算匹配上,should 子句里的条件不会对结果有影响,只会影响分数的计算。
    • 如果 bool query 是在 filter context 下,且没有包含 must 子句和 filter 子句,此时必须任意一个 should 查询条件满足才算匹配上。

    以上行为都受 minimum_should_match 参数影响,也就是需要满足的 should 子句查询条件的最小数目。

  • must_not:其查询子句必须都不被满足。当子句是在 filter context 下时,不会计算分数且会被缓存。

Query context

在 query context 下的子句查询语义可以理解为“文档与查询有多相关?”。Es 通过分数(_score)来体现这个程度,分数越高,相关程度越高。

在 query 参数下的查询子句就受 query context 影响。

Filter context

在 filter context 下的子句查询语义可以理解为“文档是否与查询条件匹配?”。

在 filter context 下的查询不会计算分数,且往往会缓存来提升性能。

filter context 会作用于以下场景:

  • 在 bool query 下的 filter 参数与 must_not 参数

    这里有个疑问,实测使用 must_not 查询时分数都为 1.0,不确定是不是固定的呢?

  • 在 constant_score 查询下的 filter 参数

  • filter 聚合


用下面的官方例子来加深印象:

image.png

使用 filter 进行查询举例

  1. 单独使用 filter ,匹配文档分数为0
GET _search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}
  1. 与其他子句类型一起使用时,分数还受其他子句影响,例如下面的例子中匹配文档分数为 1.0
GET _search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}
  1. 使用 constant_score 查询时匹配文档分数都为 1.0
GET _search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

参考

Bool Query

Query and filter context