Elasticsearch — добавление фильтра обычных полей к агрегации вложенных полей

#elasticsearch #aggregation

Вопрос:

У меня есть структура документа, как показано ниже в ES:

 {
  customer_id: 1,
  is_member: true,
  purchases: [
    {
      pur_id: 1,
      pur_channel_id: 1,
      pur_amount: 100.00,
      pur_date: '2021-08-01'
    },
    {
      pur_id: 2,
      pur_channel_id: 2,
      pur_amount: 100.00,
      pur_date: '2021-08-02'
    }
  ]
},
{
  customer_id: 2,
  is_member: false,
  purchases: [
    {
      pur_id: 3,
      pur_channel_id: 1,
      pur_amount: 200.00,
      pur_date: '2021-07-01'
    },
    {
      pur_id: 4,
      pur_channel_id: 3,
      pur_amount: 300.00,
      pur_date: '2021-07-02'
    }
  ]
}
 

Я хочу агрегировать сумму по purchases.pur_channel_id, а также для каждой субагрегации я хочу добавить агрегацию субсуммы по документам, содержащим «is_member=false», поэтому я составил следующий запрос:

 { 
  "size": 0,
  "query": {
     "match_all": {}
   }
 },
"aggs": {
  "purchases": {
    "nested": {
      "path": "purchases"
    },
    "aggs": {
       "pur_channel_id": {
         "terms": {
           "field": "purchases.pur_channel_id",
           "size": 10
         },
         "aggs": {
           "none_member": {
             "filter": {
               "term": {
                 "is_member": false
               }
             },
             "aggs": {
               "none_member_amount": {
                 "sum": {
                   "field": "purchases.pur_amount"
                 }
               }
             }
           },
           "aggs": {
             "pur_channel_amount": {
               "sum": {
                   "field": "purchases.pur_amount"
               }    
             }
           }
         }
       }
    }
  }
}
 

Запрос выполняется успешно, в то время как я получил 0 для всех «none_member_amount». Интересно, что обычное поле, возможно, не может быть добавлено внутри вложенной агрегации.

Пожалуйста, помогите! Спасибо.

Ответ №1:

Вложенная агрегация выполняется на уровне вложенных блоков, поэтому ваш запрос ищет поле is_member во вложенных документах. Чтобы присоединиться обратно к родительскому документу, вам необходимо использовать обратную вложенную агрегацию, или вы можете переместить проверку is_member перед вложенной агрегацией с помощью агрегации фильтров.