Elasticsearch 除了提供常规的平均聚合计算,还提供了加权平均值的聚合(Weighted Avg Aggregation)计算,这些值(权重与数值)可以从文档中的特定数字字段中提取。
在计算常规平均值时,我们可以认为每个数据点(datapoint)都具有相等的权重,且它们对最终值的贡献相同。然而,加权平均对每个数据点的加权值不同。每个数据点对最终值的贡献量是从文档中提取的,或由脚本提供的。
公式
加权平均值的计算公式如下:
∑(value * weight) / ∑(weight)
可以将常规平均值视为每个值的隐式权重值为 1。
相关参数
加权平均值计算主要参数(或关键字)有 weighted_avg、value、weight 等。
weighted_avg 参数
名称 | 描述 | 是否必需 |
---|---|---|
value | 提供值的字段或脚本的配置 | 必需 |
weight | 提供权重的字段或脚本的配置 | 必需 |
format | 数字回复的格式 | 可选 |
value_type | 未映射字段或脚本的 values 的相关提示 | 可选 |
value 参数
名称 | 描述 | 是否必需 |
---|---|---|
field | 应当从中提取值的字段 | 必需 |
missing | 如果字段完全丢失,则使用的值 | 可选 |
weight 参数
名称 | 描述 | 是否必需 |
---|---|---|
field | 应当从中提取权重的字段 | 必需 |
missing | 如果字段完全丢失,则使用的权重 | 可选 |
missing values
missing 参数定义应如何处理缺少值的文档。
默认情况下,如果 value 缺少该字段,则忽略该文档,并将聚合移至下一个文档。如果在常规平均值聚合计算中,如果缺少该字段,weight 默认为 1。
GET /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade",
"missing": 2
},
"weight": {
"field": "weight",
"missing": 3
}
}
}
}
}
示例
一般示例
假设我们的文档有一个 grade
字段,其包含 0~100 数值分数,此外,还存在 weight
字段,其是一个包含任意数值权重的字段,我们可以使用以下方法计算加权平均值:
GET /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade"
},
"weight": {
"field": "weight"
}
}
}
}
}
返回结果如下:
{
...
"aggregations": {
"weighted_grade": {
"value": 70.0
}
}
}
需要注意的是,虽然每个字段允许多个值,但仅允许一个权重。如果聚合遇到的文档具有多个权重(例如,weight 字段是多值字段),它将引发异常。如果遇到这种情况,则需要 script 为权重字段指定 a,然后使用脚本将多个值组合成一个要使用的值。
脚本示例
值和权重都可以从脚本中定义。以下例子针对 grade 和 weight 字段通过脚本进行了加 1,并重新定义。
GET /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"script": "doc.grade.value + 1"
},
"weight": {
"script": "doc.weight.value + 1"
}
}
}
}
}