elasticsearch嵌套对象分组

首先创建两条数据,两条数据中有一个district字段,表示涉及到的地区,district是个数组,district下包含province和city

PUT test/data/1
{
  "district":[
    {"province":"江苏省",
      "city":["南京市"]
    },{
      "province":"广东省",
      "city":["广州市"]
    }
    ]
}

PUT test/data/2
{
  "district":[
    {"province":"四川省",
      "city":["成都市"]
    },{
      "province":"浙江省",
      "city":["杭州市"]
    }
    ]
}
假如想对省份聚合,很简单,执行下面语句:

GET test/data/_search
{
  "aggs": {
    "province_group": {
      "terms": {
        "field": "district.province.keyword",
        "size": 10
      }
    }
  }
}
聚合结果如下,可以看出聚合结果并没有什么问题:


接下来再加一层聚合,在省份下面加一层按城市聚合,统计每个省份下每个城市的数量:

GET test/data/_search
{
  "aggs": {
    "province_group": {
      "terms": {
        "field": "district.province.keyword",
        "size": 10
      },
      "aggs": {
        "city_group": {
          "terms": {
            "field": "district.city.keyword",
            "size": 10
          }
        }
      }
    }
  }
}
ES的分组结果如下:

现在问题来了,四川省明明只有一个成都市,为什么会出现一个杭州市的分组,其他省份的问题也如此。

查看官方文档,因为添加数据之前没有设置映射,district字段默认映射为object类型,district是一个对象数组,ES会将它处理为如下的扁平式键值对的结构:

以文档2为例:

{

    "district.province": ["四川省","浙江省"]

    "district.city": ["成都市","杭州市"]

 }

从扁平式的键值对结构中已经看不出省和市的对应关系,因此,在分组的时候就出现了上面的问题,四川省下会有成都市和杭州市的分组。

使用ES的嵌套对象nested object可以解决这个问题,每一个嵌套对象都会被索引为一个隐藏的独立文档,对象中字段的相关性被保留了下来。

还以文档2为例,如果使用nested object,会变成如下形式,省份与城市之前的关系被保留了下来:

{

    "district.province": "四川省"

    "district.city": ["成都市"]

 }

{

    "district.province": "浙江省"

    "district.city": ["杭州市"]

 }

使用嵌套对象需要设置映射,设置映射也很简单,只需在district下加一个type为nested的属性:

PUT test/data/_mapping
{
      "data": {
        "properties": {
          "district": {
            "type": "nested",
            "properties": {
              "city": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "province": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              }
            }
          }
        }
      }
}
对嵌套对象使用聚合时,语句也有些变化:

GET test/data/_search
{
  "aggs": {
    "district": {
      "nested": {
        "path": "district"
      }, 
        "aggs": {
          "province_group": {
            "terms": {
              "field": "district.province.keyword",
              "size": 10
            },
            "aggs": {
              "city_group": {
                "terms": {
                  "field": "district.city.keyword",
                  "size": 10
                }
              }
            }
          }
        }
      
    }
  }
}
聚合结果:

ES版本:6.1

参考:https://www.elastic.co/guide/cn/elasticsearch/guide/cn/nested-objects.html


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值