Агрегации: аналитика поверх поиска

Узнаём, как Elasticsearch превращается из поисковика в аналитический движок с помощью агрегаций.

Агрегации — это вычисления статистики и группировок поверх найденных документов: средние, суммы, количества по категориям.

Зачем

Поиск отвечает «какие документы подходят». Агрегации отвечают «а что в этих документах в сумме»: сколько товаров в каждой категории, средняя цена по бренду, число заказов по дням. Это та самая аналитика, ради которой Elasticsearch ставят на логи и метрики — он считает её на лету по миллионам документов.

Два больших класса

КлассЧто делаетПримеры
Метрическиесчитают одно число по набору документовavg, sum, min, max, cardinality
Бакетныераскладывают документы по группам (корзинам)terms, range, date_histogram

Метрическая агрегация

{
  "size": 0,
  "aggs": {
    "srednyaya_cena": { "avg": { "field": "price" } }
  }
}

"size": 0 говорит «сами документы не возвращай, только агрегацию» — экономит трафик, когда нужна одна цифра. Результат придёт в поле aggregations.srednyaya_cena.value.

Бакетная агрегация

Группировка по полю keyword — самая частая. «Сколько товаров в каждой категории»:

{
  "size": 0,
  "aggs": {
    "po_kategoriyam": {
      "terms": { "field": "category", "size": 10 }
    }
  }
}

В ответе — список бакетов: key (значение категории) и doc_count (сколько документов в ней).

Вложенные агрегации

Бакетные и метрические комбинируются: «средняя цена в каждой категории» — сначала группируем по категории, внутри считаем среднее.

{
  "size": 0,
  "aggs": {
    "po_kategoriyam": {
      "terms": { "field": "category" },
      "aggs": {
        "srednyaya_cena": { "avg": { "field": "price" } }
      }
    }
  }
}

Так строятся дашборды Kibana: бакеты задают оси и группы, метрики — значения.

Как работает под капотом

Агрегации считаются по тем же документам, что подошли под query (если запрос есть). Каждый шард локально строит свои бакеты и метрики, а координатор сводит частичные результаты в общий. Важно: terms агрегация по умолчанию приблизительна для большого числа уникальных значений — каждый шард шлёт свой топ, и при сведении возможна небольшая погрешность в «хвосте». Для точных значений по полю с тысячами категорий это нужно учитывать.

Частые ошибки

  • terms по полю text. Группировать нужно по keyword: text разбит на термы, и группировка по нему даст бессмыслицу (или ошибку про fielddata). Для группировки и сортировки используйте keyword-версию поля.
  • Забыть size: 0. Если агрегация — единственная цель, без "size": 0 ES зря вернёт ещё и 10 документов.
  • Тяжёлые агрегации на горячем пути. Агрегации по миллионам документов с высокой кардинальностью затратны; о цене — в уроке про ошибки.

Итоги

  • Метрические агрегации считают число (avg, sum...), бакетные группируют документы (terms, range...).
  • Их можно вкладывать друг в друга — это основа дашбордов.
  • Группируйте по keyword, а не по text; "size": 0 убирает лишние документы из ответа.
Проверьте себя
1. Чем метрические агрегации отличаются от бакетных?
AМетрические группируют документы, бакетные считают число
BМетрические считают одно число (avg, sum), бакетные раскладывают документы по группам (terms, range)
CМежду ними нет разницы
DБакетные работают только с числами
2. По какому типу поля нужно делать terms-агрегацию для группировки?
Atext
Bkeyword
Cdate
Dboolean