ElasticSearch7.6学习日记之聚合:指标聚合

脚本聚合框架有助于基于搜索查询提供聚合数据。它基于称为聚合的简单构建块,可以进行组合以构建复杂的数据摘要。

聚合可以看作是在一组文档上建立分析信息的工作单元。执行的上下文定义此文档集是什么(例如,在已执行的查询/搜索请求的过滤器的上下文中执行顶级聚合)。

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

桶装:生成存储桶的一组聚合,其中每个存储桶都与一个和一个文档条件相关联。执行聚合时,将对上下文中的每个文档评估所有存储桶条件,并且当条件匹配时,该文档将被视为“落入”相关存储桶。到聚合过程结束时,我们将得到一个存储桶列表-每个存储桶都有一组“属于”的文档。

公制:聚集可跟踪和计算一组文档的指标。

矩阵:一类聚合,可在多个字段上进行操作,并根据从请求的文档字段中提取的值生成矩阵结果。与指标和存储桶聚合不同,此聚合系列尚不支持脚本。

管道:汇总其他汇总及其相关指标的输出的汇总

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

构建聚合

以下代码段捕获了聚合的基本结构:

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

JSON中的aggregations对象(aggs也可以使用键)保存要计算的聚合。每个集合都与用户定义的逻辑名称相关联(例如,如果集合计算平均价格,则将其命名为avg_price)。这些逻辑名称还将用于唯一地标识响应中的聚合。每个聚合都有特定的类型(<aggregation_type>在上面的代码段中),通常是命名聚合主体中的第一个键。每种聚合类型都定义自己的主体,具体取决于聚合的性质(例如,avg特定字段上的汇总将定义将在其上计算平均值的字段)。在聚合类型定义的同一级别上,可以选择定义一组其他聚合,尽管仅当您定义的聚合具有存储特性时才有意义。在这种情况下,将为存储桶聚合构建的所有存储桶计算您在存储桶聚合级别上定义的子聚合。例如,如果您在聚合下定义一组range聚合,则将为定义的范围存储区计算子聚合。

价值观来源

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

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

Elasticsearch在映射中使用字段的类型,以弄清楚如何运行聚合并设置响应格式。但是,在两种情况下,Elasticsearch无法找出此信息:未映射的字段(例如,在多个索引之间的搜索请求中,只有其中一些具有该字段的映射)和纯脚本。在这种情况下,可以使用value_type选项为Elasticsearch提供提示,该选项接受以下值:stringlong(适用于所有整数类型), double(适用于所有十进制类型,例如floatscaled_floatdate, ipboolean

一、指标汇总

1.平均聚合

single-value度量聚集,计算的是从聚集的文档中提取数值的平均数。这些值可以从文档中的特定数字字段中提取,也可以由提供的脚本生成。

假设数据由代表学生考试成绩(介于0到100之间)的文档组成,我们可以使用以下方法取平均分数:

POST /exams/_search?size=0
{
    "aggs" : {
        "avg_grade" : { "avg" : { "field" : "grade" } }
    }
}

以上汇总计算了所有文档的平均成绩。聚合类型为avg,该field设置定义将在其上计算平均值的文档的数字字段。上面将返回以下内容:

{
    ...
    "aggregations": {
        "avg_grade": {
            "value": 75.0
        }
    }
}

聚合的名称(avg_grade)还可以用作键名,通过该键可以从返回的响应中检索聚合结果。

Script

根据Script计算平均成绩:

POST /exams/_search?size=0
{
    "aggs" : {
        "avg_grade" : {
            "avg" : {
                "script" : {
                    "source" : "doc.grade.value"
                }
            }
        }
    }
}

这会将script参数解释为inline具有painless脚本语言且没有脚本参数的脚本。要使用存储的脚本,请使用以下语法:

POST /exams/_search?size=0
{
    "aggs" : {
        "avg_grade" : {
            "avg" : {
                "script" : {
                    "id": "my_script",
                    "params": {
                        "field": "grade"
                    }
                }
            }
        }
    }
}

Script的值

事实证明,该考试远远超出了学生的水平,因此需要进行成绩更正。我们可以使用Script的值来获取新的平均值:

POST /exams/_search?size=0
{
    "aggs" : {
        "avg_corrected_grade" : {
            "avg" : {
                "field" : "grade",
                "script" : {
                    "lang": "painless",
                    "source": "_value * params.correction",
                    "params" : {
                        "correction" : 1.2
                    }
                }
            }
        }
    }
}

缺失值

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

POST /exams/_search?size=0
{
    "aggs" : {
        "grade_avg" : {
            "avg" : {
                "field" : "grade",
                "missing": 10 
            }
        }
    }
}

2.加权平均聚合

single-value度量聚集,计算数字值的加权平均值被从聚合文档中提取。这些值可以从文档中的特定数字字段中提取。

在计算常规平均值时,每个数据点都具有相等的``权重''...它对最终值的贡献均等。另一方面,加权平均对每个数据点的加权不同。每个数据点对最终值的贡献量是从文档中提取的,或由脚本提供的。

作为公式,加权平均值为 ∑(value * weight) / ∑(weight)

可以将规则平均值视为每个值的隐式权重为的加权平均值1

 

表3. weighted_avg参数

参数名称 描述 需要 默认值

value

提供值的字段或脚本的配置

需要

 

weight

提供权重的字段或脚本的配置

需要

 

format

数字响应格式化程序

可选的

 

value_type

有关纯脚本或未映射字段的值的提示

可选的

 

valueweight对象有每场具体配置:

 

表4. value参数

参数名称 描述 需要 默认值

field

应当从中提取值的字段

需要

 

missing

如果字段完全丢失,则使用的值

可选的

 

表5. weight参数

参数名称 描述 需要 默认值

field

应从中提取权重的字段

需要

 

missing

如果字段完全丢失,则使用的权重

可选的

 

范例

如果我们的文档有一个"grade"包含0-100数值分数的"weight"字段和一个包含任意数值权重的字段,我们可以使用以下方法计算加权平均值:

POST /exams/_search
{
    "size": 0,
    "aggs" : {
        "weighted_grade": {
            "weighted_avg": {
                "value": {
                    "field": "grade"
                },
                "weight": {
                    "field": "weight"
                }
            }
        }
    }
}

产生如下响应:

{
    ...
    "aggregations": {
        "weighted_grade": {
            "value": 70.0
        }
    }
}

虽然每个字段允许多个值,但仅允许一个权重。如果聚合遇到的文档具有多个权重(例如,weight字段是多值字段),它将引发异常。如果遇到这种情况,则需要script指定为权重字段 ,然后使用脚本将多个值组合成一个要使用的值。

该单个权重将独立应用于从value字段中提取的每个值。

此示例说明如何使用单个权重对具有多个值的单个文档进行平均:

POST /exams/_doc?refresh
{
    "grade": [1, 2, 3],
    "weight": 2
}

POST /exams/_search
{
    "size": 0,
    "aggs" : {
        "weighted_grade": {
            "weighted_avg": {
                "value": {
                    "field": "grade"
                },
                "weight": {
                    "field": "weight"
                }
            }
        }
    }
}

这三个值(123)将作为独立值包括在内,其权重为2

{
    ...
    "aggregations": {
        "weighted_grade": {
            "value": 2.0
        }
    }
}

聚合返回2.0结果,这与我们手工计算时所期望的相匹配: ((1*2) + (2*2) + (3*2)) / (2+2+2) == 2


脚本

值和权重都可以从脚本而不是字段中派生。作为一个简单的示例,以下内容将使用脚本在文档的等级和权重中添加一个:

POST /exams/_search
{
    "size": 0,
    "aggs" : {
        "weighted_grade": {
            "weighted_avg": {
                "value": {
                    "script": "doc.grade.value + 1"
                },
                "weight": {
                    "script": "doc.weight.value + 1"
                }
            }
        }
    }
}

缺少值

missing参数定义应如何处理缺少值的文档。默认行为是不同的valueweight

默认情况下,如果value缺少该字段,则忽略该文档,并将聚合移至下一个文档。如果weight缺少该字段,则假定其权重为1(类似于正常平均值)。

可以使用以下missing参数覆盖这两个默认值: 

POST /exams/_search
{
    "size": 0,
    "aggs" : {
        "weighted_grade": {
            "weighted_avg": {
                "value": {
                    "field": "grade",
                    "missing": 2
                },
                "weight": {
                    "field": "weight",
                    "missing": 3
                }
            }
        }
    }
}

3.基数聚合

single-value度量聚集,计算不同的值的近似计数。值可以从文档中的特定字段中提取,也可以由脚本生成。

假设您正在为商店的销售建立索引,并希望计算与查询匹配的已售产品的唯一数量:

POST /sales/_search?size=0
{
    "aggs" : {
        "type_count" : {
            "cardinality" : {
                "field" : "type"
            }
        }
    }
}

产生的响应为:

{
    ...
    "aggregations" : {
        "type_count" : {
            "value" : 3
        }
    }
}


精确控制

此聚合还支持以下precision_threshold选项:

POST /sales/_search?size=0
{
    "aggs" : {
        "type_count" : {
            "cardinality" : {
                "field" : "type",
                "precision_threshold": 100 
            }
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章