Elasticsearch7.4中的Weighted Avg aggregation(加权平均聚合)也是一种单一值指标聚合,通过提取参与统计的文档中的数值进行加权平均计算而得。这些获取的数值可以是参与聚合文档的某个指定字段的值,也可以通过脚本计算而得。
当计算一般的平均数时,每个参与计算的数值具有相等的权重,也就是对最后的结果影响是一样多的。而加权平均数计算时,每个数值的权重不相同。每个参与聚合的文档就成为一个数据端点(datapoint),每个数据端点为最后结果的贡献值是由参与聚合的文档字段或是脚本来确定的。
计算公式
加权平均的计算公式是∑(value * weight) / ∑(weight)
。
其中value为每个参与聚合的文档的值,weight为对应值的权重值。
一般的平均值计算可以认为是一种每个值的权重都是1的特殊的加权平均运算。
weighted_avg参数
参数名 | 说明 | 是否必须 |
value | 文档字段或是脚本的配置信息,用以说明参与计算的数值的来源 | required |
weight | 文档字段或是脚本的配置信息,用以说明参与计算的权重值 | required |
format | 数值型数字格式 | optional |
value_type | 纯脚本或是未映射字段的值的可能类型 | optional |
value和weight都有自己的特定的配置规范。
1、value参数
参数名 | 说明 | 是否必须 |
field | 定义参与计算的数值的来源字段,值为文档字段名 | required |
missing | 指定的字段没有值时的代替数值 | optional |
2、weight参数
参数名 | 说明 | 是否必须 |
field | 定义参与计算的权重值的来源字段,值为文档字段名 | required |
missing | 指定的字段没有值时的权重值 | optional |
例子
示例数据的grade字段包含3个值,当允许含有多个值的字段参与计算时,也只有一个权重值参与计算。如果一个聚合统计中指定的权重字段包含有多个值时,系统会抛出异常。如果确实需要多个权重参与计算,可以通过script来组合计算生成单一的权重值。
下面的例子中,1、2、3三个数值分别以2的权重参与计算,聚合的结果为((1*2) + (2*2) + (3*2)) / (2+2+2) == 2
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"
}
}
}
}
}
脚本例子
无论是“value”和“weight”参数值都可以从脚本中计算获取。下面的例子中,value和weight值分别是grade、weight两个字段值基础上加1。
POST /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"script": "doc.grade.value + 1"
},
"weight": {
"script": "doc.weight.value + 1"
}
}
}
}
}
缺省值
“missing”参数定义了文档中对应的value和weight缺失时如何对待。未定义value和weight的missing参数时,两者的默认处理方式不相同:
默认情况下,如果“value”字段缺失的话,当前文档就会被忽略,聚合操作就会移动到下一个文档。如果是“weight”字段缺失的话,就会假定权重为1(就跟普通的平均计算一样)。如果定义了missing参数,就会覆盖默认的处理方式。
POST /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade",
"missing": 2
},
"weight": {
"field": "weight",
"missing": 3
}
}
}
}
}