管道(pipeline)聚合

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

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

管道聚合可以引用执行计算所需的聚合,方法是使用buckets_path参数来指示所需度量的路径。 定义这些路径的语法可以在下面的buckets_path语法部分找到。

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

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

buckets_path语法

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

AGG_SEPARATOR       =  `>` ;
METRIC_SEPARATOR    =  `.` ;
AGG_NAME            =  <the name of the aggregation> ;
METRIC              =  <the name of the metric (in case of multi-value metrics aggregation)> ;
MULTIBUCKET_KEY     =  `[<KEY_NAME>]`
PATH                =  <AGG_NAME><MULTIBUCKET_KEY>? (<AGG_SEPARATOR>, <AGG_NAME> )* ( <METRIC_SEPARATOR>, <METRIC> ) ;

例如,路径"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" 
            }
        }
    }
}

buckets_path指示 max_bucket 聚合,我们需要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聚合中获取所有桶

特殊的路径

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聚合的桶

处理聚合名称中的点

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

"buckets_path": "my_percentile[99.9]"

处理数据中的间隙(gap)

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

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

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

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