Elasticsearch сумма, основанная на условии - PullRequest
0 голосов
/ 29 сентября 2019

У меня есть эти фиктивные данные, которые я хочу сгруппировать по name, затем есть поле total, которое является суммой полей value только , если статус 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
}]

Это похоже на распространенный случай, но пока я нашел много информации о фильтрации, но не об этом конкретном случае.

1 Ответ

0 голосов
/ 29 сентября 2019

ОК, я нашел два способа сделать это.

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.

...