ES 支持类似于在SQL中使用 ANDOR 以及 NOT 的运算, 称之为布尔查询(Boolean Query),如:

[1] - must:文档必须符合其中所有的查询条件,包含多个条件时类似于SQL中的AND

[2] - should:文档必须符合其中任意一个及以上查询条件(可由minimum_should_match指定需要满足的条件数量),包含多个条件时类似于SQL中的OR

[3] - must_not:文档必须不符合其中所有的查询条件,类似于SQL中的NOT,且返回的结果的分值都为0

[4] - filter:效果与使用must相同,但不影响查询结果的分值(score)

ES 使用布尔查询时,需要将查询的条件写在bool查询语句中,且同个bool查询语句可以有多个不同的条件,如:

{
  "query": {
    "bool": {
      "must": {
        "term": {
          "age": 20
        }
      },
      "must_not": {
        "term": {
          "gender": "male"
        }
      }
    }
  }
}

该查询是,返回 age 值为 20,且 gender 值不为 male 的文档结果.

其等同于:

SELECT * FROM xxx WHERE age = 20 AND gender != "male";

1. must 查询

当使用 must查询时,文档必须符合其中包括的所有查询条件.

must查询只包括一个查询条件时,可在DSL(Domain Specific Language,即 ES 使用的结构化查询语言)中使用JSON对象的形式表示,如:

{
  "query": {
    "bool": {
      "must": {
        "term": {
          "age": 20
        }
      }
    }
  }
}

其等同于:

SELECT * FROM xxx WHERE age = 20;

使用must时可以同时指定多个查询条件,在DSL中它以数组的形式表示,效果类似于SQL中的AND运算,如:

{
  "query": {
    "bool": {
      "must": [
        { "term": { "age": 20 } },
        { "term": { "gender": "male" } }
      ]
    }
  }
}

其等同于:

SELECT * FROM xxx WHERE age = 20 AND gender = "male";

2. fliter 查询

使用 filter 查询时其效果等同于 must 查询,但不同于 must 查询的是,filter 查询不参与查询结果的分值计算,它返回的文档的分值始终为0.

filter 的使用场景适合于过滤不需要的文档,但又不影响最终计算的得分.

如:

{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

该查询是,返回所有 status 的值为"active"的文档,其得分均为0.0.

3. should 查询

should 查询类似于SQL中的OR语句,当其中包括两个及两个以上的条件时,其查询的结果必须至少满足其中一个.

当只有一个查询条件时,即结果必须满足该条件,如:

{
  "query": {
    "bool": {
      "should": [
        { "term": { "age": 20 } },
        { "term": { "gender": "male" } },
        { "range": { "height": { "gte": 170 } } },
      ]
    }
  }
}

其等同于:

SELECT * FROM xxx WHERE age = 20 OR gender = "male" or height >= 170;

should 查询与SQL中的OR运算较为不同的一点是,should 查询可以使用 minimum_should_match 参数指定至少需要满足几个条件. 例如,查询的结果需要满足两个或两个以上的查询条件:

{
  "query": {
    "bool": {
      "should": [
        { "term": { "age": 20 } },
        { "term": { "gender": "male" } },
        { "term": { "height": 170 } },
      ],
      "minimum_should_match": 2
    }
  }
}

在同一个 bool 语句中若不存在 mustfilter 时,minimum_should_match 默认的值为1,即至少要满足其中一个条件;但若有其它 mustfilter 存在时,minimum_should_match 默认值为0。

例如,所有返回的文档age值必定为20,但其中可能包括有status值不为"active"的文档. 若需要二者同时生效,可在bool查询中增加一个参数"minimum_should_match": 1.

{
  "query": {
    "bool": {
      "must": {
        "term": {
          "age": 20
        },
      },
      "should": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}

4. must_not 查询

must_not查询类似于SQL语句中的NOT运算,它将只返回不满足指定条件的文档. 例如:

{
  "query": {
    "bool": {
      "must_not": [
        { "term": { "age": 20 } },
        { "term": { "gender": "male" } }
      ]
    }
  }
}

其等同于:

SELECT * FROM xxx WHERE age != 20 AND gender != "male";

另外,must_notfilter相同,采用过滤器执行而不需要计算文档的得分,所以返回的结果对应的分值为0.

5. 布尔组合查询

ES 也可以在各个查询中进行嵌套查询. 但需要注意的是,布尔查询必须包含在bool查询语句中,所以在嵌套查询中必须在内部再次使用bool查询语句.

如:

{
  "query": {
    "must": [
      {
        "bool": {
          "should": [
            { "term": { "age": 20 } },
            { "term": { "age": 25 } }
          ]
        }
      },
      {
        "range": {
          "level": {
            "gte": 3
          }
        }
      }
    ]
  }
}

其等同于:

SELECT * FROM xxx WHERE (age = 20 OR age = 25) AND level >= 3;

再如:

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user.id" : "kimchy" }
      },
      "filter": {
        "term" : { "tags" : "production" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

6.参考

[1] - Elasticsearch布尔查询及其组合查询 - 2020.11.17

[2] - Elasticsearch - Boolean query

Last modification:March 21st, 2021 at 06:58 pm