Elasticsearch 基础教程

Elasticsearch 高级教程

Elasticsearch 插件

Elasticsearch 笔记

Elasticsearch 指标聚合之 Weighted Avg Aggregation

Elasticsearch(Es)聚合查询(指标聚合、桶聚合) Elasticsearch(Es)聚合查询(指标聚合、桶聚合)


Elasticsearch 除了提供常规的平均聚合计算,还提供了加权平均值的聚合(Weighted Avg Aggregation)计算,这些值(权重与数值)可以从文档中的特定数字字段中提取。在计算常规平均值时,我们可以认为每个数据点(datapoint)都具有相等的权重,且它们对最终值的贡献相同。然而,加权平均对每个数据点的加权值不同。每个数据点对最终值的贡献量是从文档中提取的,或由脚本提供的。

公式

加权平均值的计算公式如下:

∑(value * weight) / ∑(weight)

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

相关参数

加权平均值计算主要参数(或关键字)有 weighted_avg、value、weight 等。

weighted_avg 参数

weighted_avg 参数
名称 描述 是否必需
value 提供值的字段或脚本的配置 必需
weight 提供权重的字段或脚本的配置 必需
format 数字回复的格式 可选
value_type 未映射字段或脚本的 values 的相关提示 可选

value 参数

value 参数
名称 描述 是否必需
field 应当从中提取值的字段 必需
missing 如果字段完全丢失,则使用的值 可选

weight 参数

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"
        }
      }
    }
  }
}