2024-03-13  阅读(1)
原文作者:吴声子夜歌 原文地址: https://blog.csdn.net/cold___play/article/details/133797768

聚合

聚合框架用于根据搜索查询提供聚合数据。聚合可以看作在一组文档上构建分析信息的工作单元。执行上下文定义此文档集是什么, 例如,顶级聚合在搜索请求的已执行查询或筛选器的上下文中执行。

聚合有许多不同的类型,每种类型都有自己的目的和输出。为了 更好地理解这些类型,通常将它们分为四大类:

  1. 存储桶聚合 :构建存储桶(bucket)的聚合系列,其中每个存储桶都与键和文档相关联。当执行聚合时,将对上下文中的每个文档评估所有bucket 条件。当条件匹配时,文档将被视为“属于”相关bucket。在聚合过程结束时,我们将得到一个存储桶列表——每个存储桶都有一组属于它的文档。
  2. 度量值聚合 :在一组文档上跟踪和计算度量值(metrics)(一个数字)的聚 合。
  3. 矩阵聚合 :对多个字段进行操作并根据从请求的文档字段中提取的值生成矩阵结果的聚合系列。此聚合系列尚不支持脚本功能。
  4. 管道聚合 :聚合其他聚合的输出及其相关度量值的聚合。

存储桶聚合可以具有子聚合(度量值聚合或存储桶聚合),在其父聚合生成的存储桶下计算子聚合。嵌套聚合的级别深度没有硬限制 (可以将聚合嵌套在“父”聚合下,它本身就是另一个更高级别聚合 的子聚合)。

1、Metric——度量值聚合

度量值聚合系列中的聚合基于以某种方式从要聚合的文档中提取 的值计算聚合值。这些值通常从文档的字段中提取(使用字段数 据),但也可以使用脚本生成。

数值聚合是一种特殊类型的metrics聚合,它输出是数值。一些聚合输出单个数字度量值(例如avg),称为单值数值度量聚合 (single-value numeric metrics aggregation),其他聚合生成多 个度量值(例如stats),称为多值数值度量聚合(multi-value numeric metrics aggregation)。当这些聚合用作某些存储桶聚合的直接子聚合时,单值和多值数字聚合的区别是需要注意的,某些存储桶聚合能够根据每个存储桶中的数值聚合只对返回的存储桶进行排序。

1.1、avg——均值聚合

均值聚合(avg)是一种单值数值度量聚合,计算从聚合文档中 提取的数值的平均值。这些值可以从文档中的特定数字字段中提取, 也可以由提供的脚本生成。

计算银行账户结欠平均值:聚合的名称(上面的avg_balance)也用作键,也可以自定义的一 个标志符,通过该键可以从返回的响应中检索聚合结果,聚合类型为avg,field定义将计算平均值的文档的数字字段。

    GET /bank/_search
    {
      "aggs": {
        "avg_balance": {
          "avg": {
            "field": "balance"
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "avg_balance" : {
          "value" : 25714.837
        }
      }
    }
1.1.1、使用脚本计算

也可以通过脚本计算平均值:

    GET /bank/_search
    {
      "aggs": {
        "avg_balance": {
          "avg": {
            "script": {
              "source": "doc.balance.value"
            }
          }
        }
      },
      "size": 0
    }
1.1.2、动态参数修正

如果平均值超出了正常范围,需要进行修正。可以使用 动态参数脚本获取新的平均值:

    GET /bank/_search
    {
      "aggs": {
        "avg_balance": {
          "avg": {
            "field": "balance",
            "script": {
              "lang": "painless",
              "source": "_value * params.correction",
              "params": {
                "correction": 1.2
              }
            }
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 16,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "avg_balance" : {
          "value" : 30857.804399999997
        }
      }
    }
1.1.3、missing参数——指定缺省值

missing参数定义如何处理缺少值的文档。默认情况下,它们将 被忽略,但也可以将它们视为具有值:

    GET /bank/_search
    {
      "aggs": {
        "avg_balance": {
          "avg": {
            "field": "balance",
            "missing": 10
          }
        }
      },
      "size": 0
    }

所有的度量聚合都支持脚本功能,对缺少值的处理机制也是相同的。

1.2、min——最小值聚合

    GET /bank/_search
    {
      "aggs": {
        "min_balance": {
          "min": {
            "field": "balance"
          }
        }
      },
      "size": 0
    }

1.3、max——最大值聚合

    GET /bank/_search
    {
      "aggs": {
        "max_balance": {
          "max": {
            "field": "balance"
          }
        }
      },
      "size": 0
    }

1.4、sum——求和聚合

    GET /bank/_search
    {
      "aggs": {
        "sum_balance": {
          "sum": {
            "field": "balance"
          }
        }
      },
      "size": 0
    }

1.5、cardinality——基数统计聚合

计数聚合是一种计算不同值的近似计数的单值数值度量聚合。值 可以从文档中的特定字段中提取,也可以由脚本生成。

    GET /bank/_search
    {
      "aggs": {
        "age_count": {
          "cardinality": {
            "field": "age"
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 2,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "age_count" : {
          "value" : 21
        }
      }
    }

text 类型是分析型类型,默认是不允许进行聚合操作的,如果相对 text 类型进行聚合操作,需要设置其 fielddata 属性为 true,这种方式虽然可以使 text 类型进行聚合操作,但是无法满足精准聚合,如果需要精准聚合,可以设置字段的子域为 keyword。

1.5.1、precision_threshold参数

precision_threshold选项允许以内存开销交换准确性,并定义 唯一的计数,低于该计数的计数是接近准确值的;超过这个值,计数 可能会变得更不准确。支持的最大值为40000,高于此值的阈值将与 40000的阈值具有相同的效果。默认值为3000。

计算精确计数需要将值加载到哈希集中并返回其大小。当处理数 据量比较大时,由于所需的内存使用量和节点之间的每个分片集的通 信需求将占用集群的太多资源,所以哈希集合不会扩太大。

此cardinality聚合基于HyperlogLog++算法,该算法基于散列进 行计数,该散列具有一些有趣属性值:

  • 可配置的精度,决定了如何用内存换取精度。
  • 在少量数集上具有出色的精度。
  • 固定内存使用:无论是否有数百或数十亿个唯一值,内存使 用都仅取决于配置的精度。
    GET /bank/_search
    {
      "aggs": {
        "age_count": {
          "cardinality": {
            "field": "age",
            "precision_threshold": 100
          }
        }
      },
      "size": 0
    }

1.6、stats——基本统计聚合

基本统计,一次性返回 count、max、min、avg、sum:

    GET /bank/_search
    {
      "aggs": {
        "stats_query": {
          "stats": {
            "field": "balance"
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "stats_query" : {
          "count" : 1000,
          "min" : 1011.0,
          "max" : 49989.0,
          "avg" : 25714.837,
          "sum" : 2.5714837E7
        }
      }
    }

1.7、extended_stats——扩展统计聚合

是旧版stats(统计聚 合)的扩展版本,其中添加了额外的计量值,如平方和、方差、标准 偏差和标准偏差界限。

    GET /bank/_search
    {
      "aggs": {
        "extended_stats_query": {
          "extended_stats": {
            "field": "balance"
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 3,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "extended_stats_query" : {
          "count" : 1000,
          "min" : 1011.0,
          "max" : 49989.0,
          "avg" : 25714.837,
          "sum" : 2.5714837E7,
          "sum_of_squares" : 8.58626807735E11,
          "variance" : 1.9737396579843104E8,
          "variance_population" : 1.9737396579843104E8,
          "variance_sampling" : 1.975715373357668E8,
          "std_deviation" : 14048.984511288745,
          "std_deviation_population" : 14048.984511288745,
          "std_deviation_sampling" : 14056.014276307733,
          "std_deviation_bounds" : {
            "upper" : 53812.80602257749,
            "lower" : -2383.1320225774907,
            "upper_population" : 53812.80602257749,
            "lower_population" : -2383.1320225774907,
            "upper_sampling" : 53826.86555261546,
            "lower_sampling" : -2397.191552615466
          }
        }
      }
    }

extended_stats 聚 合 返 回 包 括 一 个 名 为 std_deviation_bounds的对象,该对象提供一个与平均值正负两个 标准差的间隔。这是一种可视化数据差异的有用方法。如果需要不同的边界,例如三个标准偏差,可以在请求中设置sigma:

    GET /bank/_search
    {
      "aggs": {
        "extended_stats_query": {
          "extended_stats": {
            "field": "balance",
            "sigma": 3
          }
        }
      },
      "size": 0
    }

sigma参数用来控制应显示多少标准偏差+/-与平均值。
sigma可以是任何非负浮点数,如1.5,值0有效,但只返回上界 和下界的平均值。

默认情况下会显示标准偏差及其边界,但它们并不总是适用于所 有数据集。数据必须是正态分布的。标准偏差后面的统计数据假定为 正态分布的数据,因此,如果数据严重向左或向右倾斜,返回的值将 是具有误导性的。

1.8、percentiles——百分位统计

百分位数聚合是一种多值数值聚合,它计算从聚合文档中提取的数值的一个或多个百分位数。这些值可以从文档中的特定数字字段中提取,也可以由提供的脚本生成。

百分位数表示观察值的某个百分比出现的点。例如,95%是大于 观察值95%的值。

百分位数通常用于查找异常值。在正态分布中,0.13%和 99.87%表示区间上下限与平均值的三个标准差。任何超出三个标准 差区间的数据通常被视为异常。

当检索到一个百分位数范围时,它们可以用来估计数据分布,并 确定数据是否是歪斜的、双峰的等。

    GET /bank/_search
    {
      "aggs": {
        "per_age": {
          "percentiles": {
            "field": "age"
          }
        }
      },
      "size": 0
    }

默认情况下,百分位数度量将生成百分位数范围:[1、5、25、 50、75、95、99]。

    {
      "took" : 36,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "per_age" : {
          "values" : {
            "1.0" : 20.0,
            "5.0" : 21.0,
            "25.0" : 25.0,
            "50.0" : 31.0,
            "75.0" : 35.0,
            "95.0" : 39.0,
            "99.0" : 40.0
          }
        }
      }
    }

从结果中可以看出,年龄分布在20~40之间,主要分布在25-35之间。
如果我们只对极端值、异常值感兴趣,可以指定我们感兴趣的百分比:

    GET /bank/_search
    {
      "aggs": {
        "per_age": {
          "percentiles": {
            "field": "age",
            "percents": [
              1,
              5,
              95,
              99
            ]
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 9,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "per_age" : {
          "values" : {
            "1.0" : 20.0,
            "5.0" : 21.0,
            "95.0" : 39.0,
            "99.0" : 40.0
          }
        }
      }
    }

默认情况下,keyed标志设置为true,它将唯一的字符串键与每 个bucket相关联,并将范围作为哈希而不是数组返回。将keyed标志 设置为false将禁用此行为:

    GET /bank/_search
    {
      "aggs": {
        "per_age": {
          "percentiles": {
            "field": "age",
            "keyed": false,
            "percents": [
              1,
              5,
              95,
              99
            ]
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 2,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "per_age" : {
          "values" : [
            {
              "key" : 1.0,
              "value" : 20.0
            },
            {
              "key" : 5.0,
              "value" : 21.0
            },
            {
              "key" : 95.0,
              "value" : 39.0
            },
            {
              "key" : 99.0,
              "value" : 40.0
            }
          ]
        }
      }
    }

1.9、percentile_rank——百分比排名聚合

百分比排名聚合是一种多值数值度量聚合,它计算从聚合文档中 提取的数值的一个或多个百分位数排名。

这里有另外一个紧密相关的度量叫 percentile_ranks 。 percentiles 度量告诉我们落在某个百分比以下的所有文档的最小值。例如,如果 50 百分位是 119ms,那么有 50% 的文档数值都不超过 119ms。 percentile_ranks 告诉我们某个具体值属于哪个百分位。119ms 的 percentile_ranks 是在 50 百分位。 这基本是个双向关系,例如:

  • 50 百分位是 119ms。
  • 119ms 百分位等级是 50 百分位。
    GET /bank/_search
    {
      "aggs": {
        "per_age_ranks": {
          "percentile_ranks": {
            "field": "age",
            "values": [20, 25, 35, 40]
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 2,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "per_age_ranks" : {
          "values" : {
            "20.0" : 4.3,
            "25.0" : 26.400000000000002,
            "35.0" : 75.6,
            "40.0" : 100.0
          }
        }
      }
    }

1.10、top_hits——顶部命中聚合

顶部命中(top_hits)聚合跟踪正在聚合的最相关若干文档。此聚合器用作子聚合器,以便每个bucket可以聚合顶部匹配的文档。

top_hits聚合器可以有效地用于通过bucket聚合器按特定字段对结果集进行分组。一个或多个bucket聚合器确定将结果集切片到哪个 属性中。

top_hits聚合器支持的参数如下:

  • from:要获取的第一个结果的偏移量(组内偏移量,由于每 个分组的结果数不同,有可能会造成有的组没有结果)。
  • size:每个桶返回的结果集的最大数量。默认情况下,返回 前三个匹配的匹配。
  • sort:如何对最匹配的匹配进行排序。默认情况下,命中文 档按主查询的分数排序。

通过示例讲解,先准备索引和数据。这里以菜谱为例,name为 菜谱名,cla为菜系,rating为用户的累积平均评分。

    PUT /recipes
    {
      "mappings": {
        "properties": {
          "name": {
            "type": "text"
          },
          "rating": {
            "type": "float"
          },
          "cla": {
            "type": "keyword"
          }
        }
      }
    }
    
    POST /recipes/_bulk
    {"index": {"_id":1}}
    {"name":"清蒸鱼头", "rating":1,"cla":"湘菜"}
    {"index": {"_id":2}}
    {"name":"剁椒鱼头", "rating":2,"cla":"湘菜"}
    {"index": {"_id":3}}
    {"name":"红烧鲫鱼", "rating":3,"cla":"湘菜"}
    {"index": {"_id":4}}
    {"name":"鲫鱼汤(辣)", "rating":3,"cla":"湘菜"}
    {"index": {"_id":5}}
    {"name":"鲫鱼汤(微辣)", "rating":4,"cla":"湘菜"}
    {"index": {"_id":6}}
    {"name":"鲫鱼汤(变态辣)", "rating":5,"cla":"湘菜"}
    {"index": {"_id":7}}
    {"name":"广式鲫鱼汤", "rating":5,"cla":"粤菜"}
    {"index": {"_id":8}}
    {"name":"鱼香肉丝", "rating":2,"cla":"川菜"}
    {"index": {"_id":9}}
    {"name":"奶油鲍鱼汤", "rating":2,"cla":"西菜"}

每个菜系展示三个菜,并按评分排序

    GET /recipes/_search
    {
      "query": {
        "match": {
          "name": "鱼"
        }
      },
      "sort": [
        {
          "rating": {
            "order": "desc"
          }
        }
      ],
      "aggs": {
        "cal": {
          "terms": {
            "field": "cla",
            "size": 10
          },
          "aggs": {
            "rated": {
              "top_hits": {
                "sort": [
                  {"rating": {"order": "desc"}}
                ],
                "size": 3,
                "from": 0
              }
            }
          }
        }
      },
      "size": 0,
      "from": 0
    }

返回:

    {
      "took" : 209,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 9,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "cal" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "湘菜",
              "doc_count" : 6,
              "rated" : {
                "hits" : {
                  "total" : {
                    "value" : 6,
                    "relation" : "eq"
                  },
                  "max_score" : null,
                  "hits" : [
                    {
                      "_index" : "recipes",
                      "_type" : "_doc",
                      "_id" : "6",
                      "_score" : null,
                      "_source" : {
                        "name" : "鲫鱼汤(变态辣)",
                        "rating" : 5,
                        "cla" : "湘菜"
                      },
                      "sort" : [
                        5.0
                      ]
                    },
                    {
                      "_index" : "recipes",
                      "_type" : "_doc",
                      "_id" : "5",
                      "_score" : null,
                      "_source" : {
                        "name" : "鲫鱼汤(微辣)",
                        "rating" : 4,
                        "cla" : "湘菜"
                      },
                      "sort" : [
                        4.0
                      ]
                    },
                    {
                      "_index" : "recipes",
                      "_type" : "_doc",
                      "_id" : "3",
                      "_score" : null,
                      "_source" : {
                        "name" : "红烧鲫鱼",
                        "rating" : 3,
                        "cla" : "湘菜"
                      },
                      "sort" : [
                        3.0
                      ]
                    }
                  ]
                }
              }
            },
            {
              "key" : "川菜",
              "doc_count" : 1,
              "rated" : {
                "hits" : {
                  "total" : {
                    "value" : 1,
                    "relation" : "eq"
                  },
                  "max_score" : null,
                  "hits" : [
                    {
                      "_index" : "recipes",
                      "_type" : "_doc",
                      "_id" : "8",
                      "_score" : null,
                      "_source" : {
                        "name" : "鱼香肉丝",
                        "rating" : 2,
                        "cla" : "川菜"
                      },
                      "sort" : [
                        2.0
                      ]
                    }
                  ]
                }
              }
            },
            {
              "key" : "粤菜",
              "doc_count" : 1,
              "rated" : {
                "hits" : {
                  "total" : {
                    "value" : 1,
                    "relation" : "eq"
                  },
                  "max_score" : null,
                  "hits" : [
                    {
                      "_index" : "recipes",
                      "_type" : "_doc",
                      "_id" : "7",
                      "_score" : null,
                      "_source" : {
                        "name" : "广式鲫鱼汤",
                        "rating" : 5,
                        "cla" : "粤菜"
                      },
                      "sort" : [
                        5.0
                      ]
                    }
                  ]
                }
              }
            },
            {
              "key" : "西菜",
              "doc_count" : 1,
              "rated" : {
                "hits" : {
                  "total" : {
                    "value" : 1,
                    "relation" : "eq"
                  },
                  "max_score" : null,
                  "hits" : [
                    {
                      "_index" : "recipes",
                      "_type" : "_doc",
                      "_id" : "9",
                      "_score" : null,
                      "_source" : {
                        "name" : "奶油鲍鱼汤",
                        "rating" : 2,
                        "cla" : "西菜"
                      },
                      "sort" : [
                        2.0
                      ]
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    }

1.11、value_count——单值度量聚合

以按照字段统计文档数量(包含指定字段的文档数量):

    GET /bank/_search
    {
      "aggs": {
        "age_type": {
          "value_count": {
            "field": "age"
          }
        }
      },
      "size": 0
    }

返回:

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

1.12、geo_bounds——地理范围聚合

地理范围聚合是一种多值数值聚合,它计算包含字段所有的 geo_point值的边界框(矩形)。示例如下:

    PUT /museums
    {
      "mappings": {
        "properties": {
          "location": {
            "type": "geo_point"
          }
        }
      }
    }
    
    POST /museums/_bulk?refresh
    {"index":{"_id": 1}}
    {"location":"52.374081,4.912350", "name":"NEMO Science Museum"}
    {"index":{"_id": 2}}
    {"location":"52.369219,4.901618", "name":"Museum Het Rembrandthuis"}
    {"index":{"_id": 3}}
    {"location":"52.371667,4.914722", "name":"Nederiands Scheepvaartmuseum"}
    {"index":{"_id": 4}}
    {"location":"51.222900,4.405200", "name":"Letterenhuis"}
    {"index":{"_id": 5}}
    {"location":"48.861111,2.336389", "name":"Musee du Louvre"}
    {"index":{"_id": 6}}
    {"location":"48.860000,2.327000", "name":"Musee d'Orsay"}
    
    POST /museums/_search?size=0
    {
      "query": {
        "match": {
          "name": "musee"
        }
      },
      "aggs": {
        "viewport": {
          "geo_bounds": {
            "field": "location",
            "wrap_longitude": true
          }
        }
      }
    }
  • geo_bounds聚合指定用于获取边界的字段。
  • wrap_longitude是一个可选参数,用于指定是否允许边界框与国际日期行重叠,默认值为true。

返回:

    {
      "took" : 3,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 2,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "viewport" : {
          "bounds" : {
            "top_left" : {
              "lat" : 48.86111099738628,
              "lon" : 2.3269999679178
            },
            "bottom_right" : {
              "lat" : 48.85999997612089,
              "lon" : 2.3363889567553997
            }
          }
        }
      }
    }

1.13、geo_centroid——地理距离质心聚合

地理距离质心聚合是一种单值数值聚合,它从地理点数据类型字 段的所有坐标值计算质心的聚合。示例如下:

    PUT /museums
    {
      "mappings": {
        "properties": {
          "location": {
            "type": "geo_point"
          }
        }
      }
    }
    
    POST /museums/_bulk?refresh
    {"index":{"_id":1}}
    {"location":"52.374081,4.912350","city":"Amsterdam", "name":"NEMO Science Museum"}
    {"index":{"_id":2}}
    {"location":"52.369219,4.901618","city":"Amsterdam", "name":"Museum Het Rembrandthuis"}
    {"index":{"_id":3}}
    {"location":"52.371667,4.914722","city":"Amsterdam", "name":"NederlandsScheepvaartmuseum"}
    {"index":{"_id":4}}
    {"location":"51.222900,4.405200","city":"Antwerp", "name":"Letterenhuis"}
    {"index":{"_id":5}}
    {"location":"48.861111,2.336389","city":"Paris", "name":"Musee du Louvre"}
    {"index":{"_id":6}}
    {"location":"48.860000,2.327000","city":"Paris", "name":"Musee d'Orsay"}
    
    POST /museums/_search?size=0
    {
      "aggs": {
        "centroid": {
          "geo_centroid": {
            "field":"location"
          }
        }
      }
    }

返回:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 6,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "centroid" : {
          "location" : {
            "lat" : 51.00982965203002,
            "lon" : 3.9662131341174245
          },
          "count" : 6
        }
      }
    }

geo-centroid聚合也可以作为子聚合。

2、Bucketing——存储桶聚合

存储桶聚合不会像metrics聚合那样在字段上计算度量值,而是 创建一个桶(bucket)。每个bucket都与一个条件(取决于聚合类 型)相关联,该条件确定当前上下文中的文档是否“落入”其中。换 句话说,bucket有效地定义了文档集。除了bucket本身之外, bucket聚合还计算并返回“落入”每个bucket的文档数。

与metrics聚合不同,存储桶聚合可以容纳子聚合。这些子聚合 将针对其“父”存储桶聚合创建的存储桶进行聚合。

不同的bucket聚合器有不同的分桶(bucketing)(文档属于哪 个桶)策略。一些定义单个存储桶,一些定义固定数量的多个存储 桶,另一些则在聚合过程中动态创建存储桶。

单个响应中允许的最大存储桶数受到名为search.max_buckets的动态集群设置的限制。它默认为10000,尝试返回超过限制的请求 将失败,并出现异常。

2.1、terms——分组聚合

Term聚合是一种多桶值聚合,其中桶是动态构建的,每个唯一值 对应一个桶。

    GET /bank/_search
    {
      "aggs": {
        "age_type_count": {
          "terms": {
            "field": "age"
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 3,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "age_type_count" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 463,
          "buckets" : [
            {
              "key" : 31,
              "doc_count" : 61
            },
            {
              "key" : 39,
              "doc_count" : 60
            },
            {
              "key" : 26,
              "doc_count" : 59
            },
            {
              "key" : 32,
              "doc_count" : 52
            },
            {
              "key" : 35,
              "doc_count" : 52
            },
            {
              "key" : 36,
              "doc_count" : 52
            },
            {
              "key" : 22,
              "doc_count" : 51
            },
            {
              "key" : 28,
              "doc_count" : 51
            },
            {
              "key" : 33,
              "doc_count" : 50
            },
            {
              "key" : 34,
              "doc_count" : 49
            }
          ]
        }
      }
    }

默认情况下,Terms聚合将返回按doc_count排序的前10个存储 桶。可以通过设置size参数来更改此默认行为。

    GET /bank/_search
    {
      "aggs": {
        "age_type_count": {
          "terms": {
            "field": "age",
            "size": 50
          }
        }
      },
      "size": 0
    }

可以设置size数来定义应返回多少个Term存储桶。默认情况下, 协调搜索过程的节点将请求每个分片提供自己的顶部Term桶,一旦所 有分片响应,它将把结果合并到最终列表,然后返回给客户机。这意 味着,如果唯一Term的数目大于size,则返回的列表会稍微偏离并且 不准确(可能是Term计数稍微偏离,甚至可能是不返回本应在最大大 小的存储桶中的Term)。

如上所述,Term聚合中的文档计数(以及任何子聚合的结果)并 不总是准确的。这是因为每个分片都提供了自己的Term排序列表的视 图,并将它们组合起来给出最终视图。

通过设置order参数,可以自定义桶的排序。默认情况下,存储 桶按其文档计数降序排列。

    GET /bank/_search
    {
      "aggs": {
        "age_type_count": {
          "terms": {
            "field": "age",
            "size": 50,
            "order": {
              "_key": "asc"
            }
          }
        }
      },
      "size": 0
    }

使用min_doc_count选项,可以只返回匹配超过某个值的 Term:

    GET /bank/_search
    {
      "aggs": {
        "age_type_count": {
          "terms": {
            "field": "age",
            "size": 50,
            "order": {
              "_key": "asc"
            },
            "min_doc_count": 50
          }
        }
      },
      "size": 0
    }

在 terms 分桶的基础上,还可以对每个桶进行指标聚合。

    GET /bank/_search
    {
      "aggs": {
        "age_type_count": {
          "terms": {
            "field": "age",
            "size": 10
          },
          "aggs": {
            "avg_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 8,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "age_type_count" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 463,
          "buckets" : [
            {
              "key" : 31,
              "doc_count" : 61,
              "avg_balance" : {
                "value" : 28312.918032786885
              }
            },
            {
              "key" : 39,
              "doc_count" : 60,
              "avg_balance" : {
                "value" : 25269.583333333332
              }
            },
            {
              "key" : 26,
              "doc_count" : 59,
              "avg_balance" : {
                "value" : 23194.813559322032
              }
            },
            {
              "key" : 32,
              "doc_count" : 52,
              "avg_balance" : {
                "value" : 23951.346153846152
              }
            },
            {
              "key" : 35,
              "doc_count" : 52,
              "avg_balance" : {
                "value" : 22136.69230769231
              }
            },
            {
              "key" : 36,
              "doc_count" : 52,
              "avg_balance" : {
                "value" : 22174.71153846154
              }
            },
            {
              "key" : 22,
              "doc_count" : 51,
              "avg_balance" : {
                "value" : 24731.07843137255
              }
            },
            {
              "key" : 28,
              "doc_count" : 51,
              "avg_balance" : {
                "value" : 28273.882352941175
              }
            },
            {
              "key" : 33,
              "doc_count" : 50,
              "avg_balance" : {
                "value" : 25093.94
              }
            },
            {
              "key" : 34,
              "doc_count" : 49,
              "avg_balance" : {
                "value" : 26809.95918367347
              }
            }
          ]
        }
      }
    }

2.2、histogram——直方图聚合

直方图聚合是一种基于源的多桶值聚合,可应用于从文档中提取数值。它动态地在这些值上构建固定大小(也称为间隔)的存储桶。 例如,如果文档有一个包含价格(数字)的字段,可以配置此聚合以 动态构建间隔为5的存储桶(如果是价格,则可能表示5美元)。执行聚合时,将计算每个文档的价格字段,并将其向下舍入到最接近的存 储桶中。例如,如果价格为32,存储桶大小为5,则舍入将生成30, 因此文档将“落入”与键30关联的存储桶中。为了使其更正式,这里使用了舍入函数:

    bucket_key=Math.floor((value-offset)/interval)*interval+offset

interval必须是正十进制数字,而offset必须是[0,interval)中 的十进制(大于或等于0且小于间隔)。

  • field:用于聚合的字段。
  • interval:指定每个桶之间的间隔。该值必须是一个大于 0 的双精度浮点数。
  • keyed:默认 false,则使用数组格式返回数据;如果设置 true,则使用键值对格式返回数据。
  • missing:如果文档没有聚合的字段,则指定一个缺省值。
  • min_doc_count:每个桶中的文档数需要大于等于该值时,才会返回。如果该值大于 0,则空桶不会被返回。
  • extended_bounds:用于拓展分桶数。可以指定 min、max 值。在 min 到 max 范围内,如果遇到空桶也会进行返回。
  • hard_bounds:用于限制分桶的范围。可以指定 min、max 值。限制返回 min 到 max 范围内的所有分桶。
  • order:指定排序规则。支持 _key、_count。默认按照 _key 升序排序。
    GET /bank/_search
    {
      "aggs": {
        "ages": {
          "histogram": {
            "field": "age",
            "interval": 5
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 7,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "ages" : {
          "buckets" : [
            {
              "key" : 20.0,
              "doc_count" : 225
            },
            {
              "key" : 25.0,
              "doc_count" : 226
            },
            {
              "key" : 30.0,
              "doc_count" : 259
            },
            {
              "key" : 35.0,
              "doc_count" : 245
            },
            {
              "key" : 40.0,
              "doc_count" : 45
            }
          ]
        }
      }
    }

默认情况 下,响应将用空桶填充直方图中的间隙。由min_doc_count设置,可 以更改此行为:

    GET /bank/_search
    {
      "aggs": {
        "ages": {
          "histogram": {
            "field": "age",
            "interval": 5,
            "min_doc_count": 10
          }
        }
      },
      "size": 0
    }

默认情况下,直方图聚合返回数据本身范围内的所有存储桶,也 就是说,具有最小值的文档将确定最小存储桶(具有最小键的存储 桶),具有最大值的文档将确定最大存储桶(具有最大键的存储桶)。通常,当请求空桶时会导致混淆,特别是当数据也被过滤时。 这个很好理解,因为我们只是指定了间隔,而上限和下限是由文档的字段值决定的。

使用 hard_bounds 参数限制返回的分桶范围,即指定上限和下限:

    GET /bank/_search
    {
      "aggs": {
        "ages": {
          "histogram": {
            "field": "age",
            "interval": 5,
            "hard_bounds": {
              "min": 25,
              "max": 35
            }
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 2,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "ages" : {
          "buckets" : [
            {
              "key" : 25.0,
              "doc_count" : 226
            },
            {
              "key" : 30.0,
              "doc_count" : 259
            },
            {
              "key" : 35.0,
              "doc_count" : 245
            }
          ]
        }
      }
    }

指定 order 参数,按照文档数降序排序:

    GET /bank/_search
    {
      "aggs": {
        "ages": {
          "histogram": {
            "field": "age",
            "interval": 5,
            "hard_bounds": {
              "min": 25,
              "max": 35
            },
            "order": {
              "_count": "desc"
            }
          }
        }
      },
      "size": 0
    }

extended_bounds不会过滤存储桶。也就是说,如果 extended_bounds.min高于从文档中提取的值,文档归属到第一个 桶(扩展的extended_bounds.max和最后一个bucket也是如此)。 对于过滤桶,应该使用适当的from/to设置将直方图聚合嵌套在范围 过滤聚合下。

    GET /bank/_search
    {
      "aggs": {
        "ages": {
          "histogram": {
            "field": "age",
            "interval": 5,
            "extended_bounds": {
              "min": 0,
              "max": 50
            },
            "order": {
              "_count": "desc"
            }
          }
        }
      },
      "size": 0
    }

返回:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "ages" : {
          "buckets" : [
            {
              "key" : 30.0,
              "doc_count" : 259
            },
            {
              "key" : 35.0,
              "doc_count" : 245
            },
            {
              "key" : 25.0,
              "doc_count" : 226
            },
            {
              "key" : 20.0,
              "doc_count" : 225
            },
            {
              "key" : 40.0,
              "doc_count" : 45
            },
            {
              "key" : 0.0,
              "doc_count" : 0
            },
            {
              "key" : 5.0,
              "doc_count" : 0
            },
            {
              "key" : 10.0,
              "doc_count" : 0
            },
            {
              "key" : 15.0,
              "doc_count" : 0
            },
            {
              "key" : 45.0,
              "doc_count" : 0
            },
            {
              "key" : 50.0,
              "doc_count" : 0
            }
          ]
        }
      }
    }

2.3、date_histogram——日期直方图聚合

日期直方图聚合。属于分桶聚合。和直方图聚合相似,但是只能对日期类型的字段或者日期范围类型的字段进行聚合。

  • field:用于聚合的字段。

  • format:限制 key_as_string 返回的时间格式、以及 extended_bounds、hard_bounds 参数的 min、max 指定的时间格式。

  • time_zone:指定时区。比如 -01:00、+08:00。

  • keyed:默认 false,则使用数组格式返回数据;如果设置 true,则使用键值对格式返回数据。

  • missing:如果文档没有聚合的字段,则指定一个缺省值。

  • min_doc_count:每个桶中的文档数需要大于等于该值时,才会返回。如果该值大于 0,则空桶不会被返回。

  • extended_bounds:用于拓展分桶数。可以指定 min、max 值。在 min 到 max 范围内,如果遇到空桶也会进行返回。

  • hard_bounds:用于限制分桶的范围。可以指定 min、max 值。限制返回 min 到 max 范围内的所有分桶。

  • order:指定排序规则。支持 _key、_count。默认按照 _key 升序排序。

  • calendar_interval:指定间隔时间。支持如下几种值:
    calendar_interval:指定间隔时间。支持如下几种值:

    • minute、1m
    • hour、1h
    • day、1d
    • week、1w
    • month、1M
    • quarter、1q
    • year、1y
  • fixed_interval:指定间隔时间。支持如下几种值:n 为某个数字

    • n milliseconds、ms
    • n seconds、s
    • n minutes、m
    • n hours、h
    • n days、d

示例文档结构:

    {
      "_index" : "kibana_sample_data_flights",
      "_type" : "_doc",
      "_id" : "kNHtJ4sBksUWkUIdS2-3",
      "_score" : 1.0,
      "_source" : {
        "FlightNum" : "9HY9SWR",
        "DestCountry" : "AU",
        "OriginWeather" : "Sunny",
        "OriginCityName" : "Frankfurt am Main",
        "AvgTicketPrice" : 841.2656419677076,
        "DistanceMiles" : 10247.856675613455,
        "FlightDelay" : false,
        "DestWeather" : "Rain",
        "Dest" : "Sydney Kingsford Smith International Airport",
        "FlightDelayType" : "No Delay",
        "OriginCountry" : "DE",
        "dayOfWeek" : 0,
        "DistanceKilometers" : 16492.32665375846,
        "timestamp" : "2023-10-02T00:00:00",
        "DestLocation" : {
          "lat" : "-33.94609833",
          "lon" : "151.177002"
        },
        "DestAirportID" : "SYD",
        "Carrier" : "Kibana Airlines",
        "Cancelled" : false,
        "FlightTimeMin" : 1030.7704158599038,
        "Origin" : "Frankfurt am Main Airport",
        "OriginLocation" : {
          "lat" : "50.033333",
          "lon" : "8.570556"
        },
        "DestRegion" : "SE-BD",
        "OriginAirportID" : "FRA",
        "OriginRegion" : "DE-HE",
        "DestCityName" : "Sydney",
        "FlightTimeHour" : 17.179506930998397,
        "FlightDelayMin" : 0
      }
    }

对 timestamp 字段进行聚合,间隔为一个月。

    GET /kibana_sample_data_flights/_search
    {
      "track_total_hits": true, 
      "size": 0,
      "aggs": {
        "timestamp_histogram": {
          "date_histogram": {
            "field": "timestamp",
            "calendar_interval": "1M",
            "format": "yyyy-MM-dd"
          }
        }
      }  
    }

返回:

    {
      "took" : 16,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 13059,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "timestamp_histogram" : {
          "buckets" : [
            {
              "key_as_string" : "2023-10-01",
              "key" : 1696118400000,
              "doc_count" : 9389
            },
            {
              "key_as_string" : "2023-11-01",
              "key" : 1698796800000,
              "doc_count" : 3670
            }
          ]
        }
      }
    }

对 timestamp 字段进行聚合,间隔为 30 天。

    GET /kibana_sample_data_flights/_search
    {
      "track_total_hits": true, 
      "size": 0,
      "aggs": {
        "timestamp_histogram": {
          "date_histogram": {
            "field": "timestamp",
            "fixed_interval": "30d",
            "format": "yyyy-MM-dd"
          }
        }
      }  
    }

聚合结果:

    "aggregations" : {
     "timestamp_histogram" : {
       "buckets" : [
         {
           "key_as_string" : "2023-09-20",
           "key" : 1695168000000,
           "doc_count" : 5687
         },
         {
           "key_as_string" : "2023-10-20",
           "key" : 1697760000000,
           "doc_count" : 7372
         }
       ]
     }
    }

2.4、auto_date_histogram——自动日期直方图聚合

自动日期直方图聚合。属于分桶聚合。与日期直方图聚合相似,但是不需要指定时间间隔,只需要指定分桶数,就会自动按照最佳的时间间隔进行分桶。

  • field:用于聚合的字段。
  • buckets:指定的分桶数。默认 10。实际返回的分桶数可能会小于等于该值。
  • format:限制 key_as_string 返回的时间格式。
  • time_zone:指定时区。比如 -01:00、+08:00。
  • missing:如果文档没有聚合的字段,则指定一个缺省值。
  • mimum_interval:指定最小的时间间隔。支持 year、month、day、hour、minute、second。

时间间隔按照天对 timestamp 字段分成 10 个桶。

    GET /kibana_sample_data_flights/_search
    {
      "track_total_hits": true, 
      "size": 0,
      "aggs": {
        "timestamp_auto_date_histogram": {
          "auto_date_histogram": {
            "field": "timestamp",
            "format": "yyyy-MM-dd",
            "buckets": 10,
            "minimum_interval": "day"
          }
        }
      }  
    }

返回的聚合:

    "aggregations" : {
      "timestamp_auto_date_histogram" : {
        "buckets" : [
          {
            "key_as_string" : "2023-10-02",
            "key" : 1696204800000,
            "doc_count" : 2202
          },
          {
            "key_as_string" : "2023-10-09",
            "key" : 1696809600000,
            "doc_count" : 2177
          },
          {
            "key_as_string" : "2023-10-16",
            "key" : 1697414400000,
            "doc_count" : 2142
          },
          {
            "key_as_string" : "2023-10-23",
            "key" : 1698019200000,
            "doc_count" : 2187
          },
          {
            "key_as_string" : "2023-10-30",
            "key" : 1698624000000,
            "doc_count" : 2188
          },
          {
            "key_as_string" : "2023-11-06",
            "key" : 1699228800000,
            "doc_count" : 2163
          }
        ],
        "interval" : "7d"
      }
    }

2.5、date_range——日期区间聚合

日期区间聚合专用于日期值的范围聚合。此聚合与正常范围聚合 的主要区别在于,from值和to值可以用日期数学表达式表示,还可以 指定返回from值和to值响应字段的日期格式。请注意,此聚合包括 from值,但不包括每个范围的to值(左闭右开区间)。

    GET /kibana_sample_data_flights/_search
    {
      "size": 0,
      "aggs": {
        "day_count": {
          "date_range": {
            "field": "timestamp",
            "format": "yyyy-MM-dd", 
            "ranges": [
              {
                "from": "now-1d/d",
                "to": "now"
              }
            ]
          }
        }
      }
    }

format指定key的格式,now表示当前,1d/d表示一天,now-1d/d即为昨天,聚合统计昨天到今天:

    "aggregations" : {
      "year_count" : {
        "buckets" : [
          {
            "key" : "2023-10-12-2023-10-13",
            "from" : 1.6970688E12,
            "from_as_string" : "2023-10-12",
            "to" : 1.697183023896E12,
            "to_as_string" : "2023-10-13",
            "doc_count" : 420
          }
        ]
      }
    }

2.6、range——区间聚合

区间聚合是一种基于source的多桶值聚合,允许用户定义一组范 围,每个范围代表一个桶。在聚合过程中,将根据每个bucket范围,核查匹配的文档属于哪个桶。请注意,此聚合包括from值,但不包括 每个范围的to值,是左闭右开区间。

    GET /bank/_search
    {
      "size": 0,
      "aggs": {
        "ages_range": {
          "range": {
            "field": "age",
            "ranges": [
              {"to": 20},
              {"from": 20, "to": 30},
              {"from": 30, "to": 40},
              {"from": 40}
            ]
          }
        }
      }
    }

返回的聚合:

    "aggregations" : {
      "ages_range" : {
        "buckets" : [
          {
            "key" : "*-20.0",
            "to" : 20.0,
            "doc_count" : 0
          },
          {
            "key" : "20.0-30.0",
            "from" : 20.0,
            "to" : 30.0,
            "doc_count" : 451
          },
          {
            "key" : "30.0-40.0",
            "from" : 30.0,
            "to" : 40.0,
            "doc_count" : 504
          },
          {
            "key" : "40.0-*",
            "from" : 40.0,
            "doc_count" : 45
          }
        ]
      }
    }

也可以给每个桶自定义key值:

    GET /bank/_search
    {
      "size": 0,
      "aggs": {
        "ages_range": {
          "range": {
            "field": "age",
            "ranges": [
              {"key": "A", "to": 20},
              {"key": "B","from": 20, "to": 30},
              {"key": "C","from": 30, "to": 40},
              {"key": "D","from": 40}
            ]
          }
        }
      }
    }
    "aggregations" : {
      "ages_range" : {
        "buckets" : [
          {
            "key" : "A",
            "to" : 20.0,
            "doc_count" : 0
          },
          {
            "key" : "B",
            "from" : 20.0,
            "to" : 30.0,
            "doc_count" : 451
          },
          {
            "key" : "C",
            "from" : 30.0,
            "to" : 40.0,
            "doc_count" : 504
          },
          {
            "key" : "D",
            "from" : 40.0,
            "doc_count" : 45
          }
        ]
      }
    }

可以自由聚合嵌套:

    GET /bank/_search
    {
      "size": 0,
      "aggs": {
        "ages_range": {
          "range": {
            "field": "age",
            "ranges": [
              {"key": "A", "to": 20},
              {"key": "B","from": 20, "to": 30},
              {"key": "C","from": 30, "to": 40},
              {"key": "D","from": 40}
            ]
          },
          "aggs": {
            "range_avg": {
              "avg": {
                "field": "age"
              }
            }
          }
        }
      }
    }

2.7、missing——空值聚合

空值聚合。统计所有没有 price 字段的文档:

    GET /bank/_search
    {
      "size": 0,
      "aggs": {
        "miss_price": {
          "missing": {
            "field": "price"
          }
        }
      }
    }

返回:

    "aggregations" : {
      "miss_price" : {
        "doc_count" : 1000
      }
    }

2.8、children——根据父子关系聚合

可以根据父子文档关系进行分桶。查询子类型为 student 的文档数量:

    GET /stu_class/_search
    {
      "size": 0,
      "aggs": {
        "NAME": {
          "children": {
            "type": "student"
          }
        }
      }
    }

返回:

    "aggregations" : {
      "NAME" : {
        "doc_count" : 3
      }
    }

2.9、geo_distance——地理距离聚合

查询距离给定位置坐标500km-600km这个环形范围的文档数量:

    GET /geo/_search
    {
      "size": 0,
      "aggs": {
        "NAME": {
          "geo_distance": {
            "field": "location",
            "origin": {
              "lat": 34.288991865037524,
              "lon": 108.9404296875
            },
            "unit": "km", 
            "ranges": [
              {
                "from": 500,
                "to": 600
              }
            ]
          }
        }
      }
    }

返回:

    "aggregations" : {
      "NAME" : {
        "buckets" : [
          {
            "key" : "500.0-600.0",
            "from" : 500.0,
            "to" : 600.0,
            "doc_count" : 1
          }
        ]
      }
    }

2.10、ip_ranges——IP区间聚合

与专用日期范围聚合一样,IP类型字段也有专用范围聚合:

    GET /kibana_sample_data_logs/_search
    {
      "size": 0,
      "aggs": {
        "ips": {
          "ip_range": {
            "field": "clientip",
            "ranges": [
              {
                "from": "120.0.0.0",
                "to": "130.0.0.0"
              }
            ]
          }
        }
      }
    }
    "aggregations" : {
      "ips" : {
        "buckets" : [
          {
            "key" : "120.0.0.0-130.0.0.0",
            "from" : "120.0.0.0",
            "to" : "130.0.0.0",
            "doc_count" : 646
          }
        ]
      }
    }

IP范围也可以定义为CIDR掩码:

    GET /kibana_sample_data_logs/_search
    {
      "size": 0,
      "aggs": {
        "ips": {
          "ip_range": {
            "field": "clientip",
            "ranges": [
              {"mask": "10.0.0.0/25"},
              {"mask": "10.0.0.127/25"}
            ]
          }
        }
      }
    }
    "aggregations" : {
      "ips" : {
        "buckets" : [
          {
            "key" : "10.0.0.0/25",
            "from" : "10.0.0.0",
            "to" : "10.0.0.128",
            "doc_count" : 0
          },
          {
            "key" : "10.0.0.127/25",
            "from" : "10.0.0.0",
            "to" : "10.0.0.128",
            "doc_count" : 0
          }
        ]
      }
    }

2.11、filter——过滤器聚合

过滤器聚合。可以将符合过滤器中条件的文档分到一个桶中,然后可以求其平均值。

    GET /bank/_search
    {
      "size": 0,
      "aggs": {
        "35_age": {
          "filter": {
            "term": {
              "age": "35"
            }
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }

返回:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1000,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "aggregations" : {
        "35_age" : {
          "doc_count" : 52,
          "balance_avg" : {
            "value" : 22136.69230769231
          }
        }
      }
    }

这种聚合器本质是Term聚合中增加了过滤器。

2.12、filters——多过滤器聚合

多过滤器聚合请求定义多桶聚合,其中每个桶与一个过滤器关 联。每个bucket将收集与其关联的过滤器匹配的所有文档。

    PUT /logs/_bulk?refresh
    {"index":{"_id":1}}
    {"body": "warning: page could not be rendered"}
    {"index":{"_id":2}}
    {"body": "authentication error"}
    {"index":{"_id":3}}
    {"body": "warning: connection timed out"}
    
    GET /logs/_search
    {
      "size": 0,
      "aggs": {
        "messages": {
          "filters": {
            "filters": {
              "errors": {
                "match": {"body":"error"}
              },
              "warnings": {
                "match": {"body":"warning"}
              }
            }
          }
        }
      }
    }

在上面的例子中,分析了日志消息。聚合将生成两个日志消息集 合(桶),一个用于聚合所有包含错误的消息,另一个用于聚合所有 包含警告的消息。

    "aggregations" : {
      "messages" : {
        "buckets" : {
          "errors" : {
            "doc_count" : 1
          },
          "warnings" : {
            "doc_count" : 2
          }
        }
      }
    }

3、Matrix——矩阵聚合

此功能是试验性的,在未来的版本中可能会被更改或完全删除。

3.1、matrix_stats——矩阵统计

matrix_stats聚合是一种数值聚合,它对一组文档字段计算以下统计信息:

  • count:计算中包含的每字段样本数。
  • mean:每个字段的平均值。
  • variance:(方差,离散)每个字段的测量对样本平均值的分布情况。
  • skewness:(偏度)每个字段的测量量化平均值周围的不对称分布。
  • kurtosis:(峰态)对分布形状进行量化的字段测量。
  • covariance:(协方差)定量描述一个领域中的变化如何与另一个领域相关联的矩阵。
  • correlation:协方差(covariance)矩阵限定在-1到1(包括-1和1)范围内。 描述字段分布之间的关系。

下面的例子演示了如何使用矩阵统计来描述收入和贫困之间的关系。

    GET /_search
    {
        "aggs": {
            "statistics": {
                "matrix_stats": {
                    "fields": ["poverty", "income"]
                }
            }
        }
    }
    {
        ...
        "aggregations": {
            "statistics": {
                "doc_count": 50,
                "fields": [{
                    "name": "income",
                    "count": 50,
                    "mean": 51985.1,
                    "variance": 7.383377037755103E7,
                    "skewness": 0.5595114003506483,
                    "kurtosis": 2.5692365287787124,
                    "covariance": {
                        "income": 7.383377037755103E7,
                        "poverty": -21093.65836734694
                    },
                    "correlation": {
                        "income": 1.0,
                        "poverty": -0.8352655256272504
                    }
                }, {
                    "name": "poverty",
                    "count": 50,
                    "mean": 12.732000000000001,
                    "variance": 8.637730612244896,
                    "skewness": 0.4516049811903419,
                    "kurtosis": 2.8615929677997767,
                    "covariance": {
                        "income": -21093.65836734694,
                        "poverty": 8.637730612244896
                    },
                    "correlation": {
                        "income": -0.8352655256272504,
                        "poverty": 1.0
                    }
                }]
            }
        }
    }
  • doc_count:字段指示统计计算中涉及的文档数量。

  • matrix_stats:聚合将每个文档字段视为一个独立的样本。 参数mode控制聚合将对数组或多值字段使用什么数组值。 该参数的值可以是下列之一:

    • avg:(默认) 使用所有值的平均值。
    • min:选择最低值。
    • max:选择最高值。
    • sum:使用所有值的总和。
    • median:使用所有值的中位数。

3.2、adjacency_matrix——邻接矩阵聚合

邻接矩阵聚合返回邻接矩阵形式的桶聚合结果集。邻接矩阵聚合 请求提供一个称为过滤器表达式的集合,类似于filters聚合请求。响 应中的每个桶表示相交过滤器矩阵中的一个非空单元。

给定名为A、B和C的过滤器,响应将返回具有如图所示的存储桶。

 A   B   C 
 A  A A&B A&C
 B  B B&C
 C  C
    PUT /emails/_bulk?refresh
    {"index":{"_id":1}}
    {"accounts":["hillary","sidney"]}
    {"index":{"_id":2}}
    {"accounts":["hillary","donald"]}
    {"index":{"_id":3}}
    {"accounts":["vladimir","donald"]}
    
    
    GET /emails/_search
    {
      "size": 0,
      "aggs": {
        "interactions": {
          "adjacency_matrix": {
            "filters": {
              "grpA": {
                "terms": {
                  "accounts":["hillary","sidney"]
                }
              },
              "grpB": {
                "terms": {
                  "accounts":["hillary","donald"]
                }
              },
              "grpC": {
                "terms": {
                  "accounts":["viadimir","donald"]
                }
              }
            }
          }
        }
      }
    }

在上面的示例中,分析了电子邮件,以查看哪些组的个人交换了 邮件,分别获得每个组的计数,以及记录交互的组对的消息计数。

    "aggregations" : {
      "interactions" : {
        "buckets" : [
          {
            "key" : "grpA",
            "doc_count" : 2
          },
          {
            "key" : "grpA&grpB",
            "doc_count" : 2
          },
          {
            "key" : "grpA&grpC",
            "doc_count" : 1
          },
          {
            "key" : "grpB",
            "doc_count" : 3
          },
          {
            "key" : "grpB&grpC",
            "doc_count" : 2
          },
          {
            "key" : "grpC",
            "doc_count" : 2
          }
        ]
      }
    }

对于N个过滤器,生成的桶矩阵可以是N2/2,默认的最大值为 100个过滤器。可以使用index.max_adjacency_matrix_filters设置 更改此设置。

邻接矩阵的聚合是作用在同一字段中不同值的交叉对比和聚合(对ES来说,所有的字段都可以存为数组),所以可以看到结果集会像文章最开头的矩阵一样存在单一标签、组合标签的聚合结果的展示。

  • filters 的部分是必填的,但是里面填的内容和普通 dsl 一样,主要是为了给当前这部分数据进行分组
  • 分组之后的结果默认用 & 相连,需要自己进行和结果矩阵构建
  • 如果标签之间不存在 overlap 的结果,返回的结果就和普通的 terms 一样了

4、Pipeline——管道聚合

管道聚合处理其他聚合(而不是文档集)产生的输出,将信息添加到输出树中。 管道聚合有很多不同的类型,每一种都计算来自其他聚合的不同信息,但这些类型可以分为两类:

  • Parent:一系列管道聚合,提供其父聚合的输出,并能够计算新桶或新聚合以添加到现有桶。
  • Sibling:与同级聚合的输出提供的管道聚合,并且能够计算与同级聚合同级别的新聚合。

管道聚合可以引用执行计算所需的聚合,方法是使用buckets_path参数来指示所需度量的路径。

管道聚合不能有子聚合,但是根据类型,它可以引用buckets_path中的另一个管道,从而允许将管道聚合链接起来。

因为管道聚合只会添加到输出中,所以在链接管道聚合时,每个管道聚合的输出都将包括在最终输出中。

4.1、buckets_path语法

大多数管道聚合需要另一个聚合作为其输入。 输入聚合是通过参数buckets_path定义的,它遵循特定的格式:

  • 聚合分隔符为>
  • 指标分隔符为.
  • 聚合名为<聚合的名称>
  • 指标为<指标的名称(如果是多值度量聚合)>
  • 路径为<聚合名>[<聚合分隔符><聚合名>]*[<指标分隔符><指标>]

例如,路径"my_bucket>my_stats.avg"将指向"my_stats"度量中的avg值,该值包含在"my_bucket"桶聚合中。

路径相对于管道聚合位置; 它们不是绝对路径,并且路径不能回到聚合树的“上面”。 例如,下面这个查询将移动平均值嵌入在 date_histogram(日期直方图)中,并引用“Sibling”(同级)度量"the_sum"

    POST /_search
    {
        "aggs": {
            "my_date_histo":{
                "date_histogram":{
                    "field":"timestamp",
                    "calendar_interval":"day"
                },
                "aggs":{
                    "the_sum":{
                        "sum":{ "field": "lemmings" } 
                    },
                    "the_movavg":{
                        "moving_avg":{ "buckets_path": "the_sum" } 
                    }
                }
            }
        }
    }
  • 该度量被称为"the_sum"
  • buckets_path通过相对路径"the_sum"引用度量

buckets_path还用于 Sibling 管道聚合,其中聚合位于一系列桶的“旁边”,而不是嵌入在桶的“内部”。 例如,max_bucket聚合使用buckets_path来指定嵌入在 Sibling 聚合中的度量:

    POST /_search
    {
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    }
                }
            },
            "max_monthly_sales": {
                "max_bucket": {
                    "buckets_path": "sales_per_month>sales" 
                }
            }
        }
    }

如果 Sibling 管道聚合引用一个多桶聚合,如terms聚合,它还可以选择从多桶中选择特定的键。 例如,bucket_script可以(通过它们的桶的键)选择两个特定的桶来执行计算:

    POST /_search
    {
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sale_type": {
                        "terms": {
                            "field": "type"
                        },
                        "aggs": {
                            "sales": {
                                "sum": {
                                    "field": "price"
                                }
                            }
                        }
                    },
                    "hat_vs_bag_ratio": {
                        "bucket_script": {
                            "buckets_path": {
                                "hats": "sale_type['hat']>sales", 
                                "bags": "sale_type['bag']>sales"  
                            },
                            "script": "params.hats / params.bags"
                        }
                    }
                }
            }
        }
    }

buckets_path选择 hats 和 bags 桶(通过[‘hat’]/[‘bag’]`)专门在脚本中使用,而不是从sale_type聚合中获取所有桶

4.1.1、特殊的路径

buckets_path可以使用一个特殊的"_count"路径,而不是一个度量的路径。 这将指示管道聚合使用文档数量作为其输入。 例如,可以根据每个时段的文档数计算移动平均值(moving_avg),而不是特定的度量:

    POST /_search
    {
        "aggs": {
            "my_date_histo": {
                "date_histogram": {
                    "field":"timestamp",
                    "calendar_interval":"day"
                },
                "aggs": {
                    "the_movavg": {
                        "moving_avg": { "buckets_path": "_count" } 
                    }
                }
            }
        }
    }

通过使用_count代替度量名称,我们可以计算直方图中文档计数的移动平均值

buckets_path还可以使用_bucket_count和多桶聚合的路径,以使用管道聚合中该聚合返回的桶数,而不是度量。 例如,这里可以使用bucket_selector来过滤出不包含内部词项聚合的桶:

    POST /sales/_search
    {
      "size": 0,
      "aggs": {
        "histo": {
          "date_histogram": {
            "field": "date",
            "calendar_interval": "day"
          },
          "aggs": {
            "categories": {
              "terms": {
                "field": "category"
              }
            },
            "min_bucket_selector": {
              "bucket_selector": {
                "buckets_path": {
                  "count": "categories._bucket_count" 
                },
                "script": {
                  "source": "params.count != 0"
                }
              }
            }
          }
        }
      }
    }

通过使用_bucket_count而不是度量名称,我们可以过滤掉histo桶,其中不包含用于categories聚合的桶

4.1.2、处理聚合名称中的点

支持一种替代语法来处理名称中带有点的聚合或度量,如99.9百分位数。 该度量可以这样引用:

    "buckets_path": "my_percentile[99.9]"
4.1.3、处理数据中的间隙(gap)

现实世界中的数据通常是嘈杂的,有时包含间隙(gap),即数据根本不存在的地方。 出现这种情况有多种原因,最常见的是:

  • 落入桶中的文档不包含必需的字段
  • 没有与一个或多个桶的查询匹配的文档
  • 正在计算的度量无法生成值,可能是因为另一个相关的桶缺少值。 一些管道聚合有必须满足的特定要求(例如,由于没有之前的值,导数(derivative)不能计算第一个值的度量,HoltWinters移动平均需要“预热”数据才能开始计算,等等)

间隙策略(gap policy)是一种机制,用于在遇到“间隙”或缺失数据时通知管道聚合所需的行为。 所有管道聚合都接受gap_policy参数。 目前有两种间隙策略可供选择:

  • skip:此选项将缺失的数据视为桶不存在。 它将跳过这个桶,并使用下一个可用值继续计算。
  • insert_zeros:此选项将用零(0)替换缺失的值,管道聚合计算将照常进行。

4.2、bucket_sort——桶排序聚合

对其父多桶聚合的桶进行排序的父管道聚合。 可以指定零个或多个排序字段以及相应的排序顺序。 每个桶可以基于其_key、_count或其子聚合进行排序。 此外,可以参数from和size,以便截断结果桶。

注意:
与所有管道聚合一样,bucket_sort聚合在所有其他非管道聚合之后执行。 这意味着排序只适用于已经从父聚合返回的任何桶。 例如,如果父聚合是terms聚合,并其参数size设置为10,那么bucket_sort将只对这 10 个返回的词项桶进行排序。

参数名称 描述 是否必填 默认值
sort 排序所依据的字段列表 可选
from 给定的值之前位置的桶将被截断 可选 0
size 要返回的桶数。 可选 默认为父聚合的所有桶
gap_policy 在数据中发现间隙时应用的策略 可选 skip

根据age分组后平均值排序桶,返回前三个:

    GET /bank/_search
    {
      "size": 0, 
      "aggs": {
        "age_type": {
          "terms": {
            "field": "age",
            "size": 5
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            },
            "my_sort": {
              "bucket_sort": {
                "sort": [
                  {
                    "balance_avg": {"order": "desc"}
                  }  
                ],
                "size": 3
              }
            }
          }
        }
      }
    }

返回聚合:

    "aggregations" : {
      "age_type" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 716,
        "buckets" : [
          {
            "key" : 31,
            "doc_count" : 61,
            "balance_avg" : {
              "value" : 28312.918032786885
            }
          },
          {
            "key" : 39,
            "doc_count" : 60,
            "balance_avg" : {
              "value" : 25269.583333333332
            }
          },
          {
            "key" : 32,
            "doc_count" : 52,
            "balance_avg" : {
              "value" : 23951.346153846152
            }
          }
        ]
      }
    }

也可以使用这种聚合来截断结果桶,而不进行任何排序。 为此,只需使用from和/或size参数,无需指定sort。

4.3、avg_bucket——桶平均值聚合

一种同级管道聚合,用于计算同级聚合中指定度量的算术平均值。 指定的度量必须是数字,并且同级聚合必须是多桶聚合。

参数名称 描述 是否必填 默认值
buckets_path 脚本变量及其关联路径到我们希望用于变量的桶的映射 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 应用与此聚合的输出值的格式 可选 null

示例:统计各个年龄对应账户的结欠平均值,然后再统计所有年龄的账户结欠平均值:

    GET /bank/_search
    {
      "size": 0, 
      "aggs": {
        "age_type": {
          "terms": {
            "field": "age",
            "size": 3
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "age_balance_avg": {
          "avg_bucket": {
            "buckets_path": "age_type>balance_avg"
          }
        }
      }
    }

返回聚合:

    "aggregations" : {
      "age_type" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 820,
        "buckets" : [
          {
            "key" : 31,
            "doc_count" : 61,
            "balance_avg" : {
              "value" : 28312.918032786885
            }
          },
          {
            "key" : 39,
            "doc_count" : 60,
            "balance_avg" : {
              "value" : 25269.583333333332
            }
          },
          {
            "key" : 26,
            "doc_count" : 59,
            "balance_avg" : {
              "value" : 23194.813559322032
            }
          }
        ]
      },
      "age_balance_avg" : {
        "value" : 25592.43830848075
      }
    }

4.4、max_bucket——最大值桶聚合

一种同级管道聚合,它标识同级聚合中(所有)具有指定度量的最大值的桶,并输出桶的值和键。 指定的度量必须是数字,并且同级聚合必须是多桶聚合。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 输出值格式 可选 null

示例:计算每个年龄分组对应的账户balance平均值中最大的:

    GET /bank/_search
    {
      "size": 0, 
      "aggs": {
        "age_type": {
          "terms": {
            "field": "age",
            "size": 5
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "max_age_balance": {
          "max_bucket": {
            "buckets_path": "age_type>balance_avg"
          }
        }
      }
    }

返回聚合:

    "aggregations" : {
      "age_type" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 716,
        "buckets" : [
          {
            "key" : 31,
            "doc_count" : 61,
            "balance_avg" : {
              "value" : 28312.918032786885
            }
          },
          {
            "key" : 39,
            "doc_count" : 60,
            "balance_avg" : {
              "value" : 25269.583333333332
            }
          },
          {
            "key" : 26,
            "doc_count" : 59,
            "balance_avg" : {
              "value" : 23194.813559322032
            }
          },
          {
            "key" : 32,
            "doc_count" : 52,
            "balance_avg" : {
              "value" : 23951.346153846152
            }
          },
          {
            "key" : 35,
            "doc_count" : 52,
            "balance_avg" : {
              "value" : 22136.69230769231
            }
          }
        ]
      },
      "max_age_balance" : {
        "value" : 28312.918032786885,
        "keys" : [
          "31"
        ]
      }
    }

4.5、min_bucket——最小值桶聚合

一种同级管道聚合,它标识同级聚合中(所有)具有指定度量的最小值的桶,并输出桶的值和键。 指定的度量必须是数字,并且同级聚合必须是多桶聚合。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 输出值格式 可选 null

示例:计算每个年龄分组对应的账户balance平均值中最小的:

    GET /bank/_search
    {
      "size": 0, 
      "aggs": {
        "age_type": {
          "terms": {
            "field": "age",
            "size": 3
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "min_age_balance": {
          "min_bucket": {
            "buckets_path": "age_type>balance_avg"
          }
        }
      }
    }

4.6、sum_bucket——加总桶聚合

一种同级管道聚合,计算同级聚合中指定度量的所有桶的总和。 指定的度量必须是数字,并且同级聚合必须是多桶聚合。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 输出值格式 可选 null

示例:计算每个年龄分组对应的账户balance平均值的总和:

    GET /bank/_search
    {
      "size": 0, 
      "aggs": {
        "age_type": {
          "terms": {
            "field": "age",
            "size": 3
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "sum_age_balance": {
          "sum_bucket": {
            "buckets_path": "age_type>balance_avg"
          }
        }
      }
    }

4.7、cumulative_cardinality——累积基数聚合

一种父管道聚合,用于计算父直方图(或日期直方图date_histogram)聚合中的累积基数。 指定的度量必须是一个基数聚合,并且封闭直方图必须将min_doc_count设置为0(histogram聚合的默认值)。

cumulative_cardinality聚合对于查找“总的新项目”非常有用,比如每天访问你的网站的新访客的数量。 常规的基数聚合会告诉你每天有多少独立访问者,但不会区分“新”或“重复”的访问者。 累积基数聚合可用于确定每天有多少独立访问者是“新的”。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
format 输出值格式 可选 null

示例:计算了每日用户(users)总数的累积基数:

    GET /user_hits/_search
    {
        "size": 0,
        "aggs" : {
            "users_per_day" : {
                "date_histogram" : {
                    "field" : "timestamp",
                    "calendar_interval" : "day"
                },
                "aggs": {
                    "distinct_users": {
                        "cardinality": {
                            "field": "user_id"
                        }
                    },
                    "total_new_users": {
                        "cumulative_cardinality": {
                            "buckets_path": "distinct_users" 
                        }
                    }
                }
            }
        }
    }

返回:

    {
       "took": 11,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "users_per_day": {
             "buckets": [
                {
                   "key_as_string": "2019-01-01T00:00:00.000Z",
                   "key": 1546300800000,
                   "doc_count": 2,
                   "distinct_users": {
                      "value": 2
                   },
                   "total_new_users": {
                      "value": 2
                   }
                },
                {
                   "key_as_string": "2019-01-02T00:00:00.000Z",
                   "key": 1546387200000,
                   "doc_count": 2,
                   "distinct_users": {
                      "value": 2
                   },
                   "total_new_users": {
                      "value": 3
                   }
                },
                {
                   "key_as_string": "2019-01-03T00:00:00.000Z",
                   "key": 1546473600000,
                   "doc_count": 3,
                   "distinct_users": {
                      "value": 3
                   },
                   "total_new_users": {
                      "value": 4
                   }
                }
             ]
          }
       }
    }

请注意第二天,2019-01-02,有两个不同的用户,但由累积管道聚合生成的total_new_users度量仅增加到三个。 这意味着那天的两个用户中只有一个是新的,另一个在前一天已经出现过了。 这种情况在第三天再次发生,三个用户中只有一个是全新的。

4.8、cumulative_sum——累积总和聚合

一种父管道聚合,用于计算父直方图(或日期直方图date_histogram)聚合中指定度量的累积总和。 指定的度量必须是数字,并且封闭直方图的min_doc_count必须设置为0(histogram聚合的默认值)。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
format 输出值格式 可选 null

示例:计算每月总销售额(sales)的累计总和:

    POST /sales/_search
    {
        "size": 0,
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    },
                    "cumulative_sales": {
                        "cumulative_sum": {
                            "buckets_path": "sales" 
                        }
                    }
                }
            }
        }
    }

返回:

    {
       "took": 11,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "sales_per_month": {
             "buckets": [
                {
                   "key_as_string": "2015/01/01 00:00:00",
                   "key": 1420070400000,
                   "doc_count": 3,
                   "sales": {
                      "value": 550.0
                   },
                   "cumulative_sales": {
                      "value": 550.0
                   }
                },
                {
                   "key_as_string": "2015/02/01 00:00:00",
                   "key": 1422748800000,
                   "doc_count": 2,
                   "sales": {
                      "value": 60.0
                   },
                   "cumulative_sales": {
                      "value": 610.0
                   }
                },
                {
                   "key_as_string": "2015/03/01 00:00:00",
                   "key": 1425168000000,
                   "doc_count": 2,
                   "sales": {
                      "value": 375.0
                   },
                   "cumulative_sales": {
                      "value": 985.0
                   }
                }
             ]
          }
       }
    }

4.9、derivative——差值聚合

一种父管道聚合,用于计算父直方图(或日期直方图date_histogram)聚合中指定度量的差值。 指定的度量必须是数字,并且封闭直方图的min_doc_count必须设置为0(histogram聚合的默认值)。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 输出值格式 可选 null
4.9.1、一阶差值

计算每月总销售额(sales)的导数:

    POST /sales/_search
    {
        "size": 0,
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    },
                    "sales_deriv": {
                        "derivative": {
                            "buckets_path": "sales" 
                        }
                    }
                }
            }
        }
    }
    {
       "took": 11,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "sales_per_month": {
             "buckets": [
                {
                   "key_as_string": "2015/01/01 00:00:00",
                   "key": 1420070400000,
                   "doc_count": 3,
                   "sales": {
                      "value": 550.0
                   } 
                },
                {
                   "key_as_string": "2015/02/01 00:00:00",
                   "key": 1422748800000,
                   "doc_count": 2,
                   "sales": {
                      "value": 60.0
                   },
                   "sales_deriv": {
                      "value": -490.0 
                   }
                },
                {
                   "key_as_string": "2015/03/01 00:00:00",
                   "key": 1425168000000,
                   "doc_count": 2, 
                   "sales": {
                      "value": 375.0
                   },
                   "sales_deriv": {
                      "value": 315.0
                   }
                }
             ]
          }
       }
    }
  • 第一桶没有差值,因为我们需要至少2个数据点来计算差值
  • 差值的单位由sales聚合和父直方图隐式定义,因此在这种情况下,假设price字段的单位为 $,则其单位为 $/month。
  • 桶中的文档数量由doc_count表示
4.9.2、二阶差值

可以通过将差值管道聚合链接到另一个导数管道聚合的结果来计算二阶差值,如下例所示,该例将计算每月总销售额(sales)的一阶差值和二阶差值:

    POST /sales/_search
    {
        "size": 0,
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    },
                    "sales_deriv": {
                        "derivative": {
                            "buckets_path": "sales"
                        }
                    },
                    "sales_2nd_deriv": {
                        "derivative": {
                            "buckets_path": "sales_deriv" 
                        }
                    }
                }
            }
        }
    }
    {
       "took": 50,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "sales_per_month": {
             "buckets": [
                {
                   "key_as_string": "2015/01/01 00:00:00",
                   "key": 1420070400000,
                   "doc_count": 3,
                   "sales": {
                      "value": 550.0
                   } 
                },
                {
                   "key_as_string": "2015/02/01 00:00:00",
                   "key": 1422748800000,
                   "doc_count": 2,
                   "sales": {
                      "value": 60.0
                   },
                   "sales_deriv": {
                      "value": -490.0
                   } 
                },
                {
                   "key_as_string": "2015/03/01 00:00:00",
                   "key": 1425168000000,
                   "doc_count": 2,
                   "sales": {
                      "value": 375.0
                   },
                   "sales_deriv": {
                      "value": 315.0
                   },
                   "sales_2nd_deriv": {
                      "value": 805.0
                   }
                }
             ]
          }
       }
    }

前两个桶没有二阶差值,因为我们需要一阶差值的至少2个数据点来计算二阶差值。

4.9.3、单位

导数聚合允许指定导数值的单位。 这将在响应中返回一个额外的字段normalized_value,用于报告所需x轴单位中的导数值。 在下面的示例中,我们计算每月总销售额(sales)的导数,但要求销售额的导数以每天的销售额为单位:

    POST /sales/_search
    {
        "size": 0,
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    },
                    "sales_deriv": {
                        "derivative": {
                            "buckets_path": "sales",
                            "unit": "day" 
                        }
                    }
                }
            }
        }
    }
    {
       "took": 50,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "sales_per_month": {
             "buckets": [
                {
                   "key_as_string": "2015/01/01 00:00:00",
                   "key": 1420070400000,
                   "doc_count": 3,
                   "sales": {
                      "value": 550.0
                   } 
                },
                {
                   "key_as_string": "2015/02/01 00:00:00",
                   "key": 1422748800000,
                   "doc_count": 2,
                   "sales": {
                      "value": 60.0
                   },
                   "sales_deriv": {
                      "value": -490.0, 
                      "normalized_value": -15.806451612903226 
                   }
                },
                {
                   "key_as_string": "2015/03/01 00:00:00",
                   "key": 1425168000000,
                   "doc_count": 2,
                   "sales": {
                      "value": 375.0
                   },
                   "sales_deriv": {
                      "value": 315.0,
                      "normalized_value": 11.25
                   }
                }
             ]
          }
       }
    }
  • value以原始单位per month报告
  • normalized_value以所需的单位per day报告

4.10、percentiles_bucket——百分位数桶聚合

一种同级管道聚合,用于计算同级聚合中指定度量的所有桶的百分位数。 指定的度量必须是数字,并且同级聚合必须是多桶聚合。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 输出值格式 可选 null
percents 要计算的百分位数值的列表 可选 [1,5,25,50,75,95,99]
keyed 一个标志,是否将范围作为哈希而不是键值对数组返回 可选 true

示例:计算每月总销售额(sales)的百分位数:

    POST /sales/_search
    {
        "size": 0,
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    }
                }
            },
            "percentiles_monthly_sales": {
                "percentiles_bucket": {
                    "buckets_path": "sales_per_month>sales", 
                    "percents": [ 25.0, 50.0, 75.0 ] 
                }
            }
        }
    }
  • buckets_path指示这个 percentiles_bucket 聚合,我们要为sales_per_month日期直方图中的sales聚合计算百分位数。
  • percents指定我们希望计算哪些百分位数,在本例中,是第25、50和75个百分位。
    {
       "took": 11,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "sales_per_month": {
             "buckets": [
                {
                   "key_as_string": "2015/01/01 00:00:00",
                   "key": 1420070400000,
                   "doc_count": 3,
                   "sales": {
                      "value": 550.0
                   }
                },
                {
                   "key_as_string": "2015/02/01 00:00:00",
                   "key": 1422748800000,
                   "doc_count": 2,
                   "sales": {
                      "value": 60.0
                   }
                },
                {
                   "key_as_string": "2015/03/01 00:00:00",
                   "key": 1425168000000,
                   "doc_count": 2,
                   "sales": {
                      "value": 375.0
                   }
                }
             ]
          },
          "percentiles_monthly_sales": {
            "values" : {
                "25.0": 375.0,
                "50.0": 375.0,
                "75.0": 550.0
             }
          }
       }
    }

4.11、moving_avg——移动平均聚合

给定一系列有序的数据,移动平均聚合将在数据上滑动一个窗口,并得出该窗口的平均值。 例如,给定数据[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以计算窗口大小为5的简单移动平均值,如下所示:

    (1 + 2 + 3 + 4 + 5) / 5 = 3
    (2 + 3 + 4 + 5 + 6) / 5 = 4
    (3 + 4 + 5 + 6 + 7) / 5 = 5
    等等...

移动平均是平滑连续数据的一种简单方法。 移动平均通常应用于基于时间的数据,如股票价格或服务器指标。 平滑可用于消除高频波动或随机噪声,这使得低频趋势更容易被可视化,如季节性。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
mdel 希望使用的移动平均加权模型 可选 simple
window 在直方图上“滑动”的窗口大小 可选 5
minimize 模型是否应该在算法上最小化 可选 大多数模型用false
settings 特定于模型的设置,内容根据指定的模型而有所不同。 可选

moving_avg聚合必须嵌入一个histogram或date_histogram聚合中。 它们可以像任意其他度量聚合一样嵌入:

    POST /_search
    {
        "size": 0,
        "aggs": {
            "my_date_histo":{                
                "date_histogram":{
                    "field":"date",
                    "calendar_interval":"1M"
                },
                "aggs":{
                    "the_sum":{
                        "sum":{ "field": "price" } 
                    },
                    "the_movavg":{
                        "moving_avg":{ "buckets_path": "the_sum" } 
                    }
                }
            }
        }
    }
  • 名为“my_date_histo”的 date_histogram是在“timestamp”字段上构建的,间隔为一天
  • sum度量用于计算字段的总和。 这可以是任何度量(sum、min、max等)
  • 最后,我们指定一个moving_avg聚合,它使用“the_sum”度量作为其输入。
    {
       "took": 11,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "my_date_histo": {
             "buckets": [
                 {
                     "key_as_string": "2015/01/01 00:00:00",
                     "key": 1420070400000,
                     "doc_count": 3,
                     "the_sum": {
                        "value": 550.0
                     }
                 },
                 {
                     "key_as_string": "2015/02/01 00:00:00",
                     "key": 1422748800000,
                     "doc_count": 2,
                     "the_sum": {
                        "value": 60.0
                     },
                     "the_movavg": {
                        "value": 550.0
                     }
                 },
                 {
                     "key_as_string": "2015/03/01 00:00:00",
                     "key": 1425168000000,
                     "doc_count": 2,
                     "the_sum": {
                        "value": 375.0
                     },
                     "the_movavg": {
                        "value": 305.0
                     }
                 }
             ]
          }
       }
    }

4.12、stats_bucket——统计桶聚合

一种同级管道聚合,计算同级聚合中指定度量的所有桶的各种统计信息。 指定的度量必须是数字,并且同级聚合必须是多桶聚合。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 应用于此聚合的输出值的格式 可选 null

示例:计算月 销售额(sales) 的统计数据:

    POST /sales/_search
    {
        "size": 0,
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    }
                }
            },
            "stats_monthly_sales": {
                "stats_bucket": {
                    "buckets_path": "sales_per_month>sales" 
                }
            }
        }
    }
    {
       "took": 11,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "sales_per_month": {
             "buckets": [
                {
                   "key_as_string": "2015/01/01 00:00:00",
                   "key": 1420070400000,
                   "doc_count": 3,
                   "sales": {
                      "value": 550.0
                   }
                },
                {
                   "key_as_string": "2015/02/01 00:00:00",
                   "key": 1422748800000,
                   "doc_count": 2,
                   "sales": {
                      "value": 60.0
                   }
                },
                {
                   "key_as_string": "2015/03/01 00:00:00",
                   "key": 1425168000000,
                   "doc_count": 2,
                   "sales": {
                      "value": 375.0
                   }
                }
             ]
          },
          "stats_monthly_sales": {
             "count": 3,
             "min": 60.0,
             "max": 550.0,
             "avg": 328.3333333333333,
             "sum": 985.0
          }
       }
    }

4.13、extened_stats_bucket——扩展的统计桶聚合

一种同级管道聚合,计算同级聚合中指定度量的所有桶的各种统计信息。 指定的度量必须是数字,并且同级聚合必须是多桶聚合。

与stats_bucket聚合相比,这种聚合提供了更多的统计信息(平方和、标准差等)。

参数 描述 是否必填 默认值
buckets_path 希望找到最大值的桶的路径 必填
gap_policy 在数据中发现间隙时应用的策略 可选 skip
format 应用于此聚合的输出值的格式 可选 null
sigma 显示高于/低于平均值的标准差的个数 可选 2

示例:计算月 销售额(sales) 桶的扩展统计数据:

    POST /sales/_search
    {
        "size": 0,
        "aggs" : {
            "sales_per_month" : {
                "date_histogram" : {
                    "field" : "date",
                    "calendar_interval" : "month"
                },
                "aggs": {
                    "sales": {
                        "sum": {
                            "field": "price"
                        }
                    }
                }
            },
            "stats_monthly_sales": {
                "extended_stats_bucket": {
                    "buckets_path": "sales_per_month>sales" 
                }
            }
        }
    }
    {
       "took": 11,
       "timed_out": false,
       "_shards": ...,
       "hits": ...,
       "aggregations": {
          "sales_per_month": {
             "buckets": [
                {
                   "key_as_string": "2015/01/01 00:00:00",
                   "key": 1420070400000,
                   "doc_count": 3,
                   "sales": {
                      "value": 550.0
                   }
                },
                {
                   "key_as_string": "2015/02/01 00:00:00",
                   "key": 1422748800000,
                   "doc_count": 2,
                   "sales": {
                      "value": 60.0
                   }
                },
                {
                   "key_as_string": "2015/03/01 00:00:00",
                   "key": 1425168000000,
                   "doc_count": 2,
                   "sales": {
                      "value": 375.0
                   }
                }
             ]
          },
          "stats_monthly_sales": {
             "count": 3,
             "min": 60.0,
             "max": 550.0,
             "avg": 328.3333333333333,
             "sum": 985.0,
             "sum_of_squares": 446725.0,
             "variance": 41105.55555555556,
             "std_deviation": 202.74505063146563,
             "std_deviation_bounds": {
               "upper": 733.8234345962646,
               "lower": -77.15676792959795
             }
          }
       }
    }

Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文