Выполнять многопольные / многомерные агрегации с вложенными полями в эластичном поиске

#elasticsearch #kibana #aggregation #elasticsearch-aggregation

#elasticsearch #kibana #агрегирование #elasticsearch-агрегация

Вопрос:

Я отслеживаю посещаемость нескольких студентов. Я сохраняю их данные в индексе, как показано ниже.

В каждом документе в разделе «записи» есть несколько других полей. Следующие данные показывают, что ученик посетил 6 занятий в «понедельник».

«записи» имеют тип «вложенные».

      {
      reg_id: 1111,
      "entires" : [
        {
          id: "123"
          day: 'Monday'
        },
        {
          id: "1234",
          attendance: true
        },
        {
          id: "12345",
          classes_attended: 6
        }
      ],
    }
 

Я хочу, чтобы в каждом классе было подсчитано количество учеников за каждый день.

Например, «найдено 72 записи учащихся для «Понедельника», которые посещали 6 занятий».

Пример желаемого результата — это всего лишь пример, я полностью в порядке, если схема вывода будет изменена.

     [
      {
        "day" : "monday", 
        "classes_attended": 6,
        count: 4
      },
      {
        "day" : "monday", 
        "classes_attended": 1,
        count: 5
      },
      {
        "day" : "tuesday", 
        "classes_attended": 5,
        count: 2
      },
      {
        "day" : "tuesday", 
        "classes_attended": 6,
        count: 1
      }
    ]
 

Не уверен, как начать с запроса агрегации:

Я попытался выполнить следующий запрос, но я знаю, что это неправильное решение

 "aggs": {
    "attendance_aggs": {
      "nested": {
        "path": "entries"
      },
      "aggs": {
        "days": {
          "terms": {
            "field": "entries.day"
          },
          "aggs": {
          "attended": {
            "reverse_nested": {},
            "aggs":{
              "class_attended_day": {
                "terms": {
                  "field": "entries.classes_attended"
                },
                "aggs": {
                  "class_attended_days_count": {
                    "reverse_nested": {},
                    "aggs": {
                      "classes_attended_final": {
                        "cardinality": {
                          "field": "entries.class_attended"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
        }
      }
    }
  }
 

Ответ №1:

Неясно, что такое объект верхнего уровня, поэтому я предполагаю, что это «запись посещаемости учащихся за день». Я также не уверен, что entries.ids они представляют, но предполагаю, что они понадобятся вам позже, поэтому я оставлю их нетронутыми.

Теперь, поскольку все, что у ваших entries объектов общего, — это id , они могут быть разделены. Это означает, что вы должны использовать nested if any только в том случае, если вы используете некоторые атрибуты для всех объектов, которые нуждаются в сохранении их атрибутивных связей. Поскольку я нигде не вижу entries.id в ваших agg, я бы рекомендовал внести следующие изменения в ваше сопоставление:

 PUT students
{
  "mappings": {
    "properties": {
      "day": {                ------------
        "type": "keyword"                |
      },                                 |
      "attendance": {                    |                                
        "type": "boolean"                | <--
      },                                 |
      "classes_attended": {              |
        "type": "integer"                |
      },                     ------------
      "entries": {
        "type": "nested",
        "properties": {
          "day": {
            "type": "keyword",
            "copy_to": "day"               <--
          },
          "attendance": {
            "type": "boolean",
            "copy_to": "attendance"        <--
          },
          "classes_attended": {
            "type": "integer",
            "copy_to": "classes_attended"  <--
          }
        }
      }
    }
  }
}
 

и вот ваш запрос:

 GET students/_search
{
  "size": 0,
  "aggs": {
    "days": {
      "terms": {
        "field": "day"
      },
      "aggs": {
        "classes_attended": {
          "terms": {
            "field": "classes_attended"
          },
          "aggs": {
            "student_count": {
              "cardinality": {
                "field": "_id"
              }
            }
          }
        }
      }
    }
  }
}
 

Затем ответ может быть обработан постобработкой во все, что вы предпочитаете.


Редактировать

Вы можете перехватить reverse_nested , но вам нужно будет вернуться к нему, поскольку вы ссылаетесь на другие вложенные записи:

 GET students/_search
{
  "size": 0,
  "aggs": {
    "attendance_aggs": {
      "nested": {
        "path": "entries"
      },
      "aggs": {
        "days": {
          "terms": {
            "field": "entries.day"
          },
          "aggs": {
            "attended": {
              "reverse_nested": {},
              "aggs": {
                "class_attended_day": {
                  "nested": {
                    "path": "entries"
                  },
                  "aggs": {
                    "class_attended_day": {
                      "terms": {
                        "field": "entries.classes_attended"
                      },
                      "aggs": {
                        "classes_attended_final": {
                          "cardinality": {
                            "field": "entries.classes_attended"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
 

Комментарии:

1. Спасибо, Джо. У меня есть ключ «submit_id», который является общим для всех вложенных объектов. Можно ли придерживаться самого вложенного типа и переписать запрос. Я также готов изменить отображение индекса. Но, к вашему сведению, я использую ключ, который является общим для всех вложенных объектов. Было бы здорово, если бы я мог получить запрос без изменения сопоставления.

2. Добавлена вложенная версия к моему ответу. Но просто для ясности — я не изменял вашу вложенность. Я сгладил атрибуты на верхнем уровне, потому что вам не нужны вложенные агги для получения вашего ответа.