加权平均聚合
weighted_avg
聚合计算文档中数值的加权平均值。当您需要计算平均值但希望某些数据点具有更高权重时,此功能非常有用。
加权平均值使用公式 \(\frac{\sum_{i=1}^n \text{value}_i \cdot \text{weight}_i}{\sum_{i=1}^n \text{weight}_i}\) 计算。
参数
weighted_avg
聚合支持以下参数:
参数 | 必需/可选 | 描述 |
---|---|---|
value | 必需 | 定义如何获取要平均的数值。需要指定 field 或 script 。 |
weight | 必需 | 定义如何获取每个值的权重。需要指定 field 或 script 。 |
format | 可选 | 一个 DecimalFormat 格式化字符串。将格式化后的输出返回到聚合的 value_as_string 属性中。 |
value_type | 可选 | 使用脚本或未映射字段时,对值的类型提示。 |
您可以在 value
或 weight
中指定以下参数:
参数 | 必需/可选 | 描述 |
---|---|---|
field | 可选 | 用于值或权重的文档字段。 |
missing | 可选 | 当字段缺失时使用的默认值或权重。参见缺失值。 |
示例
首先,创建一个索引并索引一些数据。请注意,产品 C 缺少 rating
和 num_reviews
字段。
POST _bulk
{ "index": { "_index": "products" } }
{ "name": "Product A", "rating": 4.5, "num_reviews": 100 }
{ "index": { "_index": "products" } }
{ "name": "Product B", "rating": 3.8, "num_reviews": 50 }
{ "index": { "_index": "products" } }
{ "name": "Product C"}
以下请求使用 weighted_avg
聚合来计算加权平均产品评分。在此上下文中,每个产品的评分都根据其 num_reviews
进行加权。这意味着评论数量更多的产品将对最终平均值产生更大的影响,而评论数量较少的产品影响较小。
GET /products/_search
{
"size": 0,
"aggs": {
"weighted_rating": {
"weighted_avg": {
"value": {
"field": "rating"
},
"weight": {
"field": "num_reviews"
},
"format": "#.##"
}
}
}
}
示例响应
响应包含 weighted_rating
,计算方式为 weighted_avg = (4.5 * 100 + 3.8 * 50) / (100 + 50) = 4.27
。只有文档 1 和 2(包含 rating
和 num_reviews
值的文档)被纳入计算。
{
"took": 18,
"timed_out": false,
"terminated_early": true,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"weighted_rating": {
"value": 4.266666650772095,
"value_as_string": "4.27"
}
}
}
缺失值
missing
参数允许您为缺失 value
字段或 weight
字段的文档指定默认值,而不是将其从计算中排除。
例如,您可以为没有评分的产品分配一个“平均”评分 3.0,并将 num_reviews
设置为 1,以赋予它们一个小的非零权重。
GET /products/_search
{
"size": 0,
"aggs": {
"weighted_rating": {
"weighted_avg": {
"value": {
"field": "rating",
"missing": 3.0
},
"weight": {
"field": "num_reviews",
"missing": 1
},
"format": "#.##"
}
}
}
}
新的加权平均值计算方式为 weighted_avg = (4.5 * 100 + 3.8 * 50 + 3.0 * 1) / (100 + 50 + 1) = 4.26
。
{
"took": 27,
"timed_out": false,
"terminated_early": true,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"weighted_rating": {
"value": 4.258278129906055,
"value_as_string": "4.26"
}
}
}