ElasticSearch 使用详解:组合查询怎么玩

2021-12-22  本文已影响0人  you的日常

查询是一个复杂过程,特别是当查询过程中有多个条件,在 ES 中当有多个条件的时候,就得使用组合查询了。

组合查询是通过 bool 关键字来实现的,通过 mustmust_notshould 将不同的条件组合到一起,再用 bool 包裹一下作为一个整体。用来实现各种且、非、或的条件组合。

“且”条件

给定需求:

查询 class 索引中姓 deng 并且年龄是 16 的学生。

下面的查询语句中不难看出,bool 包裹了条件整体,使用 must 组合两个条件实现了“且”。

GET class/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "deng"
          }
        },
        {
          "term": {
            "age": 16
          }
        }
      ]
    }
  }
}

image

“非”条件

给定需求:

查找姓名中不包含 deng,且年龄要大于 16 岁的。

下面这条查询语句,使用 must_not 不难理解是对里面的条件做了一个“非”操作。首先使用 match Phrase查询姓名中包含 deng 的,然后再用范围查询,查询年龄小于 16 的,再取个“非”,达到了我们想要的效果。

GET class/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "name": "deng"
          }
        },
        {
          "range": {
            "age": {
              "lte": 16
            }
          }
        }
      ]
    }
  }
}

image

“或”条件

给定需求:

查询性别为“男性”或者“女性”的学生数据。

因为性别是确定的字符串,要么是 man 要么是 female,所以这是一个精确值查询的需求,因此使用 term 查询,并且因为是 sex 的字段类型是“字符串”所以加上 keyword。(这里思考一下,上个课时中说了如果不加 keyword 将不会返回查询结果,但是这里如果把 keyword 去掉也能查询相同的数据,请问是为什么?结合上节课对 keyword 的解释,你一定会找到答案的。)

GET class/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "sex.keyword": "man"
          }
        },
        {
          "term": {
            "sex.keyword":"female"
          }
        }
      ]
    }
  }
}

image

对于性别的过滤这里使用了两个 term 查询,但是是对同一个字段做出的判断,写两个 term 查询条件显得比较繁琐,这里对于同一个字段的条件判断有更简洁的写法,就是把条件放到数组中去。

这里有两个地方需要注意,第一就是 terms 而不是之前的 term,第二个就是字段后面加的是数组,而不是之前的花括号。

GET class/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "terms": {
            "sex.keyword": [
              "man",
              "famale"
            ]
          }
        }
      ]
    }
  }
}

mustshould 的组合

这里一定要注意,ES 中的条件组合跟 SQL 的逻辑稍微有点不同,ES 中 mustshould 不能够同时使用,当使用了 must 后,should 将不会在发生作用

因为 should 只是一个增加相关性分数的一个条件,当你只使用 should 的时候,如果不满足条件,那么相关性分数会比较低,就不会返回数据给你。像下面这个条件,稍微把性别改成一个不存在的 a 和 b,跟我们想的一样,并没有返回任何数据。

GET class/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "terms": {
            "sex.keyword": [
              "a",
              "b"
            ]
          }
        }
      ]
    }
  }
}

image

这里我再加上一个 must 条件做测试,结果返回了很多数据,仔细观察 _score 字段都是有值的,这些值都是来源于 must 条件,should 条件因为没有满足的所以对 _score 没有任何贡献,因此 should 字段只是能影响 _score 字段,当其他条件能够给 _score 字段带来相关性分数时候,should 条件将不会对查询结果有任何贡献,只能够让 _score 变得大一点或者没有。

GET class/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "deng"
          }
        }
      ],
      "should": [
        {
          "terms": {
            "sex.keyword": [
              "a",
              "b"
            ]
          }
        }
      ]
    }
  }
}

image

这个问题怎么解决呢?mustshould 组合是经常会遇到的问题。

上一篇下一篇

猜你喜欢

热点阅读