You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OpenSearch中创建争议嵌套交易求和值的直方图?

问题描述

我正在使用OpenSearch索引,每个文档代表一起争议,包含嵌套的交易数组。目标是计算每起争议中嵌套交易数组内transactions.transactionAmount.amountInCents字段的总和,再基于这些求和值创建直方图。

文档结构示例:

{
  "dispute_id": "123",
  "transactions": [
    {
      "transactionMerchant": "MerchantA",
      "transactionAmount": {
        "amountInCents": 1000,
        "currency": "USD"
      }
    },
    {
      "transactionMerchant": "MerchantB",
      "transactionAmount": {
        "amountInCents": 2000,
        "currency": "USD"
      }
    }
  ]
}

已尝试操作

已成功编写查询计算每起争议的交易金额总和:

POST /dispute/_search
{
  "size": 0,
  "aggs": {
    "by_dispute": {
      "terms": {
        "field": "dispute_id",
        "size": 10
      },
      "aggs": {
        "nested_transactions": {
          "nested": {
            "path": "transactions"
          },
          "aggs": {
            "transaction_sum": {
              "sum": {
                "field": "transactions.transactionAmount.amountInCents"
              }
            }
          }
        }
      }
    }
  }
}

该查询能正确返回每起争议的求和值,但尝试创建直方图时遇到嵌套聚合的限制,无法直接引用子聚合的结果。

失败尝试

尝试直接在顶级聚合中添加直方图,引用子聚合的值,但返回空桶:

POST /dispute/_search
{
  "size": 0,
  "aggs": {
    "by_dispute": {
      "terms": {
        "field": "dispute_id",
        "size": 10
      },
      "aggs": {
        "nested_transactions": {
          "nested": {
            "path": "transactions"
          },
          "aggs": {
            "transaction_sum": {
              "sum": {
                "field": "transactions.transactionAmount.amountInCents"
              }
            }
          }
        }
      }
    },
    "sum_histogram": {
      "histogram": {
        "field": "by_dispute>nested_transactions>transaction_sum.value",
        "interval": 1000
      }
    }
  }
}

返回结果片段:

"sum_histogram": {
      "buckets": []
}
解决方案

OpenSearch不支持直接在顶级聚合中引用子聚合的计算结果,需要使用**管道聚合(Pipeline Aggregation)**中的histogram_bucket来基于by_dispute聚合桶中的求和值生成直方图。

正确查询示例

POST /dispute/_search
{
  "size": 0,
  "aggs": {
    "by_dispute": {
      "terms": {
        "field": "dispute_id",
        "size": 10000  // 根据实际争议数量调整,确保覆盖所有数据
      },
      "aggs": {
        "nested_transactions": {
          "nested": {
            "path": "transactions"
          },
          "aggs": {
            "transaction_sum": {
              "sum": {
                "field": "transactions.transactionAmount.amountInCents"
              }
            }
          }
        },
        // 将嵌套聚合的求和值提取到争议桶层面
        "dispute_total": {
          "bucket_script": {
            "buckets_path": {
              "total": "nested_transactions>transaction_sum"
            },
            "script": "params.total"
          }
        }
      }
    },
    // 基于每个争议的求和值生成直方图
    "sum_histogram": {
      "histogram_bucket": {
        "buckets_path": "by_dispute>dispute_total",
        "interval": 1000,
        "keyed": true
      }
    }
  }
}

关键说明

  • bucket_script聚合:将嵌套聚合中计算出的transaction_sum提取到by_dispute的桶层面,生成dispute_total字段,为后续管道聚合提供可引用的数值。
  • histogram_bucket管道聚合:遍历by_dispute的所有桶,将每个桶的dispute_total值按照指定的interval(此处为1000分)分组,生成直方图的各个桶。
  • size参数调整:by_dispute聚合的size必须设置足够大,确保能包含所有争议文档,否则会丢失部分数据,导致直方图结果不准确。

替代方案:使用运行时字段优化性能

如果数据量较大,管道聚合的性能无法满足需求,可以在索引中添加运行时字段,提前计算每个争议的交易金额总和,之后直接对该字段做直方图聚合:

定义运行时字段(索引级别)

PUT /dispute/_mapping
{
  "runtime": {
    "total_transaction_amount": {
      "type": "long",
      "script": {
        "source": "def sum = 0; if (params._source.transactions != null) { for (t in params._source.transactions) { sum += t.transactionAmount.amountInCents; } } return sum;"
      }
    }
  }
}

直接生成直方图

POST /dispute/_search
{
  "size": 0,
  "aggs": {
    "sum_histogram": {
      "histogram": {
        "field": "total_transaction_amount",
        "interval": 1000
      }
    }
  }
}

该方案的优势是查询时无需嵌套和管道聚合,性能更优,脚本中也处理了transactions数组为空的边界情况。

内容的提问来源于stack exchange,提问作者Shahriar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:14:55