Elasticsearch 基于 array 结构 的nested类型的索引的聚合查询

这几天在做es的聚合查询,对那种一对多的产品数据查询的时候遇到了一些问题,做一下记录

1.es文档数据结构如下

=====doc 文档一
{
    "id": "IEO29R12KN912NDF893",
    "products": [
        {
            "product_name": "电视机",
            "budget": 2000
        },
        {
            "product_name": "手机",
            "budget": 851
        }
    ],
    "publish_year": "2020"
}
=====doc 文档二
{
    "id": "IQFJ019238AHJDFK1L9",
    "products": [
        {
            "product_name": "电视机",
            "budget": 2000
        },
        {
            "product_name": "相机",
            "budget": 5000
        },
        {
            "product_name": "扑克牌",
            "budget": 2
        }
    ],
    "publish_year": "2019"
}

2.我的查询需求结果是

针对每个产品名称[product_name]进行分组,并对预算[budget]求和

3.我期望的查询结果

产品名称 预算
电视机 4000
手机 851
相机 5000
扑克牌 2

4.错误的es查询以及结果

4.1查询的es语句和结果

es查询语句==简化版

{
    
    
  "from": 0,
  "size": 14,
  "aggs": {
    
    
    "aggs_of_product": {
    
    
      "terms": {
    
    
        "field": "products.product_name.keyword"
      },
      "aggs": {
    
    
        "aggs_sum_of_budget": {
    
    
          "sum": {
    
    
            "field": "products.budget"
          }
        }
      }
    }
  }doc 文档二
}

es查询的结果==简化版

{
    
    
    "aggregations": {
    
    
        "aggs_of_product": {
    
    
            "buckets": [
                {
    
    
                    "key": "电视机",
                    "doc_count": 2,
                    "aggs_sum_of_budget": {
    
    
                        "value": 9853
                    }
                },
                {
    
    
                    "key": "手机",
                    "doc_count": 1,
                    "aggs_sum_of_budget": {
    
    
                        "value": 2851
                    }
                },
                {
    
    
                    "key": "相机",
                    "doc_count": 1,
                    "aggs_sum_of_budget": {
    
    
                        "value": 7002
                    }
                },
                {
    
    
                    "key": "扑克牌",
                    "doc_count": 1,
                    "aggs_sum_of_budget": {
    
    
                        "value": 7002
                    }
                }
            ]
        }
    }
}

4.2 错误的原因

注意电视机的doc_count为2,这里我们可以根据电视,相机,扑克牌的预算和可以得出结论。以相机为例:他计算的sum值是把命中相机的[doc 文档二]下面的产品的budget预算全部求和了,这里的es聚合查询在这里就不适用了。

如果一个文档里面只有一个产品的话,那这个es查询语句查出的结果就是正确的。

5.解决方案

在经过多次的google和百度后我发现了一个问题,就是我的计算思路是没问题的,主要问题还在在products的这个字段的类型,最开始products的类型是默认的,后面需要把他改为nested[嵌套]类型的才可以

5.1 字段索引mapping的修改

之前products的mapping

{
    
    
    "mappings": {
    
    
        "properties": {
    
    
            "products": {
    
    
                "properties": {
    
    
                    "product_name": {
    
    
                        "type": "text",
                        "fields": {
    
    
                            "keyword": {
    
    
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "budget": {
    
    
                        "type": "float"
                    }
                }
            }
        }
    }
}

修改products之后的mapping

把products的字段类型改为nested嵌套类型的。
多一个 “type”: “nested”

{
    
    
    "mappings": {
    
    
        "properties": {
    
    
            "products": {
    
    
                "type": "nested",
                "properties": {
    
    
                    "product_name": {
    
    
                        "type": "text",
                        "fields": {
    
    
                            "keyword": {
    
    
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "budget": {
    
    
                        "type": "float"
                    }
                }
            }
        }
    }
}

5.2 修改后的es查询语句

{
    
    
    "aggs": {
    
    
        "nested_name": {
    
    
            "nested": {
    
    
                "path": "products"
            },
            "aggs": {
    
    
                "aggs_of_product": {
    
    
                    "terms": {
    
    
                        "field": "products.product_name.keyword"     
                    },
                    "aggs": {
    
    
                        "aggs_sum_of_budget": {
    
    
                            "sum": {
    
    
                                "field": "products.budget"
                            }
                        }
                    }
                }
            }
        }
    }
}

5.3 修改后的查询结果

{
    
    
    "aggregations": {
    
    
        "aggr_field_product": {
    
    
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 36126,
            "buckets": [
                {
    
    
                    "key": "电视机",
                    "doc_count": 2,
                    "sum_eventTime": {
    
    
                        "value": 4000
                    }
                },
                {
    
    
                    "key": "手机",
                    "doc_count": 1,
                    "sum_eventTime": {
    
    
                        "value": 851
                    }
                },
                {
    
    
                    "key": "相机",
                    "doc_count": 1,
                    "sum_eventTime": {
    
    
                        "value": 5000
                    }
                },
                {
    
    
                    "key": "扑克牌",
                    "doc_count": 1,
                    "sum_eventTime": {
    
    
                        "value": 2
                    }
                }
            ]
        }
    }
}

6.参考资料
stackoverflow-nested-array-of-objects-aggregation-in-elasticsearch
Elasticsearch 7.x Nested 嵌套类型查询-知乎
Elasticsearch Nested类型深入详解

猜你喜欢

转载自blog.csdn.net/weixin_42581660/article/details/128560202
今日推荐