基于条件的弹性求和

问题描述 投票:0回答:1

我有要按name分组的模拟数据,然后有一个total字段,该字段是value字段的总和only,如果状态为won

[{
  name: 'Foo',
  value: 12,
  status: 'won'
},
{
  name: 'Foo',
  value: 2,
  status: 'lost'
},
{
  name: 'Foo',
  value: 10,
  status: 'won'
},
{
  name: 'Bar',
  value: 4,
  status: 'won'
}]

我能够按名称分组并获得值字段的总和,但还没有弄清楚如何仅对获胜案例进行求和。

aggs: {
  by_name: {
    terms: {
      field: 'name'
    },
    aggs: {
      total_value: {
        sum: {
          field: 'value' // What I want is value if status == 'won' 
        }
      }
    }
  }

我想要的结果应类似于:

[{
  name: 'Foo',
  total_value: 22 // Currently 24
}, {
  name: 'Bar',
  total_value: 4
}]

这似乎是一个常用的情况,但是虽然我发现了很多有关过滤的信息,但不是这个特殊情况。

elasticsearch elasticsearch-aggregation
1个回答
0
投票

确定,我发现了两种方法可以做到这一点。

1。使用脚本

ES支持各种脚本语言,但已内置对Painless的支持:

aggs: {
  by_name: {
    terms: {
      field: 'name'
    },
    aggs: {
      total_value: {
        sum: {
          script: {
           lang: 'painless',
           source:doc['status'].value == 'won' ? doc['value'] : 0"
          }
        }
      }
    }
  }

2。使用嵌套分组/聚合

在我的用例中,我还需要将所有获胜和失落总计为单个字段,以获得更像结果集:

[{
  name: 'Foo',
  total_won_value: 22,
  total_won: 2
  total_lost_value: 2,
  total_lost: 1
}, {
  ...
}

虽然我可以使用一些脚本来完成此操作,但是我怀疑(尽管这必须进行测试),它的性能更高,可以通过嵌套聚合来实现。

aggs: {
  by_name: {
    terms: {
      field: 'name'
    },
    aggs: {
      by_status: {
        terms: {
          field: 'status'
        },
        aggs: {
          total_value_by_status: {
            sum: {
              field: 'value'
            }
          }
        }
      }
    }
  }
}    

第二种方法的缺点是,它很难解析结果,尤其是在类似AppSync模板的情况下。

© www.soinside.com 2019 - 2024. All rights reserved.