加权平均聚合编辑

一个 single-value 指标聚合,它计算从聚合的文档中提取的数值的加权平均值。这些值可以从文档中的特定数值字段中提取。

在计算普通平均值时,每个数据点都有相同的“权重”……它对最终值贡献相等。另一方面,加权平均值对每个数据点进行不同的加权。每个数据点对最终值的贡献量是从文档中提取的。

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

普通平均值可以被认为是加权平均值,其中每个值都有一个隐含的权重 1

表 51. weighted_avg 参数

参数名称 描述 必需 默认值

value

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

必需

weight

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

必需

format

数值响应格式化程序

可选

The value and weight objects have per-field specific configuration

表 52. value 参数

参数名称 描述 必需 默认值

field

应从中提取值的字段

必需

missing

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

可选

表 53. weight 参数

参数名称 描述 必需 默认值

field

应从中提取权重的字段

必需

missing

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

可选

示例编辑

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

response = client.search(
  index: 'exams',
  body: {
    size: 0,
    aggregations: {
      weighted_grade: {
        weighted_avg: {
          value: {
            field: 'grade'
          },
          weight: {
            field: 'weight'
          }
        }
      }
    }
  }
)
puts response
POST /exams/_search
{
  "size": 0,
  "aggs": {
    "weighted_grade": {
      "weighted_avg": {
        "value": {
          "field": "grade"
        },
        "weight": {
          "field": "weight"
        }
      }
    }
  }
}

这将产生类似于以下内容的响应

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

虽然允许每个字段有多个值,但只允许一个权重。如果聚合遇到具有多个权重的文档(例如,权重字段是多值字段),它将中止搜索。如果您遇到这种情况,您应该构建一个 运行时字段 将这些值组合成单个权重。

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

此示例展示了如何将具有多个值的单个文档与单个权重进行平均

response = client.index(
  index: 'exams',
  refresh: true,
  body: {
    grade: [
      1,
      2,
      3
    ],
    weight: 2
  }
)
puts response

response = client.search(
  index: 'exams',
  body: {
    size: 0,
    aggregations: {
      weighted_grade: {
        weighted_avg: {
          value: {
            field: 'grade'
          },
          weight: {
            field: 'weight'
          }
        }
      }
    }
  }
)
puts response
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

运行时字段编辑

如果您必须对与索引值不完全匹配的值进行求和或加权,请在 运行时字段 上运行聚合。

response = client.index(
  index: 'exams',
  refresh: true,
  body: {
    grade: 100,
    weight: [
      2,
      3
    ]
  }
)
puts response

response = client.index(
  index: 'exams',
  refresh: true,
  body: {
    grade: 80,
    weight: 3
  }
)
puts response

response = client.search(
  index: 'exams',
  filter_path: 'aggregations',
  body: {
    size: 0,
    runtime_mappings: {
      'weight.combined' => {
        type: 'double',
        script: "\n        double s = 0;\n        for (double w : doc['weight']) {\n          s += w;\n        }\n        emit(s);\n      "
      }
    },
    aggregations: {
      weighted_grade: {
        weighted_avg: {
          value: {
            script: 'doc.grade.value + 1'
          },
          weight: {
            field: 'weight.combined'
          }
        }
      }
    }
  }
)
puts response
POST /exams/_doc?refresh
{
  "grade": 100,
  "weight": [2, 3]
}
POST /exams/_doc?refresh
{
  "grade": 80,
  "weight": 3
}

POST /exams/_search?filter_path=aggregations
{
  "size": 0,
  "runtime_mappings": {
    "weight.combined": {
      "type": "double",
      "script": """
        double s = 0;
        for (double w : doc['weight']) {
          s += w;
        }
        emit(s);
      """
    }
  },
  "aggs": {
    "weighted_grade": {
      "weighted_avg": {
        "value": {
          "script": "doc.grade.value + 1"
        },
        "weight": {
          "field": "weight.combined"
        }
      }
    }
  }
}

这应该看起来像

{
  "aggregations": {
    "weighted_grade": {
      "value": 93.5
    }
  }
}

缺失值编辑

默认情况下,聚合会排除 valueweight 字段的值缺失或为 null 的文档。使用 missing 参数来指定这些文档的默认值。

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