elasticsearch 父子文档使用must not 正确姿势

需求描述:

1、基于elasticsearch 父子文档进行子条件查询父文档
2、需要查询出子文档不存在的父文档

已知文档结构:

1、父文档clue_list 关联很多的子文档,我们用roam子文档做测试!
在这里插入图片描述
2、roam子文档的结构

{
  "took" : 7,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 5.4327264,
    "hits" : [
      {
        "_index" : "clue_list",
        "_type" : "_doc",
        "_id" : "roam_668414740279590913",
        "_score" : 5.4327264,
        "_routing" : "668164507591245825",
        "_source" : {
          "companyId" : 1,
          "companyRoamCount" : 0,
          "centreRoamCount" : 0,
          "depRoamCount" : 2,
          "publicRoamCount" : 0,
          "joinFiled" : {
            "parent" : "668164507591245825",
            "name" : "roam"
          }
        }
      }
    ]
  }
}

小试牛刀

需求是查询出roam子文档不存在的数据,由于我们es的所有数据companyId == 1 我们可以用must not来排除 companyId == 1的数据

1、错误的查询方式,直接must not匹配

GET clue_list/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "joinFiled": {
              "value": "clue_list"
            }
          }
        },{
          "has_child": {
            "type": "roam",
            "query": {
              "bool": {
                "must_not": [
                  {
                    "term": {
                      "companyId": {
                        "value": 1
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

结果:

{
  "took" : 80,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

结论:直接匹配没有查询出目标数据,由于must not排除了companyId == 1的数据,但是由于我们数据库并没有其他数据,此时查询子文档返回数据为空,子文档为空匹配父文档造成返回数据为空。

2、正确的姿势,先查询出companyId == 1的数据,然后取反将must not放在外层
es执行语句:

GET clue_list/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "joinFiled": {
              "value": "clue_list"
            }
          }
        },{          
          "bool": {
            "must_not": [
              {
                "has_child": {
                  "type": "roam",
                  "query": {
                    "term": {
                      "companyId": {
                        "value": 1
                      }
                    }
                  }
                }
              }
            ]
          }
          
        }
      ]
    }
  }
}

响应数据:
在这里插入图片描述

验证第一条数据是否不存在roam子文档:
在这里插入图片描述

结论:正确查询出不存在roam子文档的数据

寄语:
es父子文档查询通过子文档过滤父文档且需要用到must not的时候,如果有子文档有为空的情况,则需要先查询不满足条件的再在父层级进行排除,如果子文档一定不会为空才能够直接进行排除操作;
当然,懒人适用的方式就是直接用第二种方案,都在上层进行排除不满足条件的数据。

  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:黑客帝国 设计师:我叫白小胖 返回首页
评论

打赏作者

BUG追踪

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值