原英文版地址: https://www.elastic.co/guide/en/elasticsearch/reference/7.7/search-aggregations.html, 原文档版权归 www.elastic.co 所有
本地英文版地址: ../en/search-aggregations.html

聚合 (aggregations)

聚合框架有助于提供基于搜索查询的聚合数据。 它基于被称为聚合(aggregations)的简单构建块,可以组合这些块来构建复杂的数据摘要。

聚合可以被看作是在一组文档上构建分析信息的工作单元。 执行的上下文定义了这个文档集是什么(例如,顶级的聚合在搜索请求的已执行的 query/filter 的上下文中执行)。

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

Bucketing
构建桶(bucket)的一系列聚合,其中每个桶都与一个 key 和一个文档标准相关联。 执行聚合时,将在上下文中的每个文档上去评估所有的桶标准,当标准匹配时,该文档将被视为“落入”相应的桶。 在聚合过程的最后,我们将得到一个桶列表——每个桶都有一组“属于”它的文档。
Metric
跟踪和计算一组文档 度量(metric) 的聚合。
Matrix
对多个字段进行操作并根据从请求的文档字段中提取的值生成 矩阵(matrix) 结果的一系列聚合。 与 metric 和 bucket 聚合不同,此聚合系列尚不支持脚本。
Pipeline
聚合其他聚合的输出及其相关度量的聚合

接下来的部分才是有趣的。 由于每个桶都有效地定义了一个文档集(属于该桶的所有文档),因此可以在桶级别关联聚合,这些聚合将在该桶的上下文中执行。 这就是聚合的真正威力所在:聚合可以嵌套!

bucketing 聚合可以有子聚合(bucketing 或 metric)。 将为其父聚合生成的桶计算子聚合。 对嵌套聚合的级别/深度没有硬性限制(可以将一个聚合嵌套在一个“父”聚合下,而这个父聚合本身是另一个更高级聚合的子聚合)。

聚合在数据的 double 表示法上进行操作。 因此,在绝对值大于 2^53 的长整型数上运行时,结果可能是近似的。

构建聚合

以下代码片段体现了聚合的基本结构:

"aggregations" : {
    "<aggregation_name>" : {
        "<aggregation_type>" : {
            <aggregation_body>
        }
        [,"meta" : {  [<meta_data_body>] } ]?
        [,"aggregations" : { [<sub_aggregation>]+ } ]?
    }
    [,"<aggregation_name_2>" : { ... } ]*
}

JSON 中的 aggregations 对象(也可以使用 aggs 作为键)保存要计算的聚合。 每个聚合都与用户定义的逻辑名称(<aggregation_name>)相关联(例如,如果聚合计算平均价格,则将其命名为avg_price是有意义的)。 这些逻辑名称还将用于唯一地标识响应中的聚合。 每个聚合都有一个特定的类型(上面代码片段中的<aggregation_type>),并且通常是命名聚合体内的第一个键。 根据聚合的性质,每种类型的聚合定义自己的主体(例如,特定字段上的 avg 聚合将定义计算平均值的字段)。 在聚合类型定义的同一级别,可以选择性的定义一组附加的聚合,但这只有在你定义的聚合具有 bucketing 性质时才有意义。 在这种情况下,将为 bucketing 聚合构建的所有桶计算在 bucketing 聚合级别定义的子聚合。 例如,如果在 range 聚合下定义了一组聚合,将为定义的范围(range)桶计算子聚合。

值的来源

一些聚合处理从聚合文档中提取的值。 通常,这些值将从指定的文档字段中提取,该字段是使用聚合的 field 键设置的。 也可以定义一个 script 来生成这些值(每个文档)。

当为聚合配置了 fieldscript 设置时,脚本将被视为value script(值脚本)。 普通脚本在文档级别进行评估(即脚本可以访问与文档相关的所有数据),而值脚本(value script)value(值)级别进行评估。 在这种模式下,从已配置的 field 中提取值,并使用 script 对这些值进行“转换”。

使用脚本时,还可以定义 langparams 设置。 前者定义了所使用的脚本语言(假设 Elasticsearch 中有合适的语言,无论是默认语言还是插件语言)。 后者支持将脚本中的所有“动态(dynamic)”表达式定义为参数,这使得脚本能够在调用之间保持静态(static)(这将确保在Elasticsearch 中使用缓存的编译过的脚本)。

Elasticsearch 使用映射(mapping)中的字段类型来确定如何运行聚合和格式化响应。 然而,在两种情况下,Elasticsearch 无法找出这些信息:未映射的字段(例如,在跨多个索引的搜索请求的情况下,只有其中一部分字段在映射中有定义) 和 纯脚本。 对于这些情况,可以使用 value_type 选项给 Elasticsearch 一个提示,该选项接受以下值:stringlong(适用于所有整数类型)、double(适用于所有十进制类型,如floatscaled_float)、dateipboolean