美文网首页
Elasticsearch 分组聚合查询(bucket) ---

Elasticsearch 分组聚合查询(bucket) ---

作者: 一位先生_ | 来源:发表于2022-06-11 12:37 被阅读0次

    Elasticsearch桶聚合,目的就是数据分组,先将数据按指定的条件分成多个组,然后对每一个组进行统计。 组的概念跟桶是等同的,在ES中统一使用桶(bucket)这个术语。

    ES桶聚合的作用跟SQL的group by的作用是一样的,区别是ES支持更加强大的数据分组能力,SQL只能根据字段的唯一值进行分组,分组的数量跟字段的唯一值的数量相等,例如: group by 店铺id, 去掉重复的店铺ID后,有多少个店铺就有多少个分组。

    ES常用的桶聚合如下:

    Terms聚合 - 类似SQL的group by,根据字段唯一值分组
    Histogram聚合 - 根据数值间隔分组,例如: 价格按100间隔分组,0、100、200、300等等
    Date histogram聚合 - 根据时间间隔分组,例如:按月、按天、按小时分组
    Range聚合 - 按数值范围分组,例如: 0-150一组,150-200一组,200-500一组。
    提示:桶聚合一般不单独使用,都是配合指标聚合一起使用,对数据分组之后肯定要统计桶内数据,在ES中如果没有明确指定指标聚合,默认使用Value Count指标聚合,统计桶内文档总数。

    1.Terms聚合
    terms聚合的作用跟SQL中group by作用一样,都是根据字段唯一值对数据进行分组(分桶),字段值相等的文档都分到同一个桶内。

    例子:

    GET /order/_search?size=0
    {
      "aggs": {
        "shop": { // 聚合查询的名字,随便取个名字
          "terms": { // 聚合类型为: terms
            "field": "shop_id" // 根据shop_id字段值,分桶
          }
        }
      }
    }
    

    等价SQL:

    select shop_id, count(*) from order group by shop_id
    

    返回结果:

    {
        ...
        "aggregations" : {
            "shop" : { // 聚合查询名字
                "buckets" : [ // 桶聚合结果,下面返回各个桶的聚合结果
                    {
                        "key" : "1", // key分桶的标识,在terms聚合中,代表的就是分桶的字段值
                        "doc_count" : 6 // 默认的指标聚合是统计桶内文档总数
                    },
                    {
                        "key" : "5",
                        "doc_count" : 3
                    },
                    {
                        "key" : "9",
                        "doc_count" : 2
                    }
                ]
            }
        }
    }
    

    2.Histogram聚合
    histogram(直方图)聚合,主要根据数值间隔分组,使用histogram聚合分桶统计结果,通常用在绘制条形图报表。

    例子:

    POST /sales/_search?size=0
    {
        "aggs" : {
            "prices" : { // 聚合查询名字,随便取一个
                "histogram" : { // 聚合类型为:histogram
                    "field" : "price", // 根据price字段分桶
                    "interval" : 50 // 分桶的间隔为50,意思就是price字段值按50间隔分组
                }
            }
        }
    }
    

    返回结果:

    {
        ...
        "aggregations": {
            "prices" : { // 聚合查询名字
                "buckets": [ // 分桶结果
                    {
                        "key": 0.0, // 桶的标识,histogram分桶,这里通常是分组的间隔值
                        "doc_count": 1 // 默认按Value Count指标聚合,统计桶内文档总数
                    },
                    { 
                        "key": 50.0,
                        "doc_count": 1
                    },
                    {
                        "key": 100.0,
                        "doc_count": 0
                    },
                    {
                        "key": 150.0,
                        "doc_count": 2
                    }
                ]
            }
        }
    }
    

    3.Date histogram聚合
    类似histogram聚合,区别是Date histogram可以很好的处理时间类型字段,主要用于根据时间、日期分桶的场景。

    例子:

    POST /sales/_search?size=0
    {
        "aggs" : {
            "sales_over_time" : { // 聚合查询名字,随便取一个
                "date_histogram" : { // 聚合类型为: date_histogram
                    "field" : "date", // 根据date字段分组
                    "calendar_interval" : "month", // 分组间隔:month代表每月、支持minute(每分钟)、hour(每小时)、day(每天)、week(每周)、year(每年)
                    "format" : "yyyy-MM-dd" // 设置返回结果中桶key的时间格式
                }
            }
        }
    }
    

    返回结果:

    {
        ...
        "aggregations": {
            "sales_over_time": { // 聚合查询名字
                "buckets": [ // 桶聚合结果
                    {
                        "key_as_string": "2015-01-01", // 每个桶key的字符串标识,格式由format指定
                        "key": 1420070400000, // key的具体字段值
                        "doc_count": 3 // 默认按Value Count指标聚合,统计桶内文档总数
                    },
                    {
                        "key_as_string": "2015-02-01",
                        "key": 1422748800000,
                        "doc_count": 2
                    },
                    {
                        "key_as_string": "2015-03-01",
                        "key": 1425168000000,
                        "doc_count": 2
                    }
                ]
            }
        }
    }
    

    4.Range聚合
    range聚合,按数值范围分桶。

    例子:

    GET /_search
    {
        "aggs" : {
            "price_ranges" : { // 聚合查询名字,随便取一个
                "range" : { // 聚合类型为: range
                    "field" : "price", // 根据price字段分桶
                    "ranges" : [ // 范围配置
                        { "to" : 100.0 }, // 意思就是 price <= 100的文档归类到一个桶
                        { "from" : 100.0, "to" : 200.0 }, // price>100 and price<200的文档归类到一个桶
                        { "from" : 200.0 } // price>200的文档归类到一个桶
                    ]
                }
            }
        }
    }
    

    返回结果:

    {
        ...
        "aggregations": {
            "price_ranges" : { // 聚合查询名字
                "buckets": [ // 桶聚合结果
                    {
                        "key": "*-100.0", // key可以表达分桶的范围
                        "to": 100.0, // 结束值
                        "doc_count": 2 // 默认按Value Count指标聚合,统计桶内文档总数
                    },
                    {
                        "key": "100.0-200.0",
                        "from": 100.0, // 起始值
                        "to": 200.0, // 结束值
                        "doc_count": 2
                    },
                    {
                        "key": "200.0-*",
                        "from": 200.0,
                        "doc_count": 3
                    }
                ]
            }
        }
    }
    

    大家仔细观察的话,发现range分桶,默认key的值不太友好,尤其开发的时候,不知道key长什么样子,处理起来比较麻烦,我们可以为每一个分桶指定一个有意义的名字。

    例子:

    GET /_search
    {
        "aggs" : {
            "price_ranges" : {
                "range" : {
                    "field" : "price",
                    "keyed" : true,
                    "ranges" : [
                        // 通过key参数,配置每一个分桶的名字
                        { "key" : "cheap", "to" : 100 },
                        { "key" : "average", "from" : 100, "to" : 200 },
                        { "key" : "expensive", "from" : 200 }
                    ]
                }
            }
        }
    }
    

    5.综合例子
    前面的例子,都是单独使用aggs聚合语句,代表直接统计所有的文档,实际应用中,经常需要配合query语句,先搜索目标文档,然后使用aggs聚合语句对搜索结果进行统计分析。

    例子:

    GET /cars/_search
    {
        "size": 0, // size=0代表不需要返回query查询结果,仅仅返回aggs统计结果
        "query" : { // 设置查询语句,先赛选文档
            "match" : {
                "make" : "ford"
            }
        },
        "aggs" : { // 然后对query搜索的结果,进行统计
            "colors" : { // 聚合查询名字
                "terms" : { // 聚合类型为:terms 先分桶
                  "field" : "color"
                },
                "aggs": { // 通过嵌套聚合查询,设置桶内指标聚合条件
                  "avg_price": { // 聚合查询名字
                    "avg": { // 聚合类型为: avg指标聚合
                      "field": "price" // 根据price字段计算平均值
                    }
                  },
                  "sum_price": { // 聚合查询名字
                    "sum": { // 聚合类型为: sum指标聚合
                      "field": "price" // 根据price字段求和
                    }
                  }
                }
            }
        }
    }
    

    聚合查询支持多层嵌套。

    相关文章

      网友评论

          本文标题:Elasticsearch 分组聚合查询(bucket) ---

          本文链接:https://www.haomeiwen.com/subject/tbnfsrtx.html