Конвейер агрегации: $match, $group, $sort

Как считать сводные показатели: данные проходят через цепочку этапов, каждый преобразует поток.

Конвейер агрегации (aggregation pipeline) — последовательность этапов, через которые документы проходят один за другим, преобразуясь на каждом шаге.

Идея конвейера

Когда нужно не просто найти документы, а посчитать сумму, среднее или количество по группам, на сцену выходит aggregate. Вы передаёте массив этапов; выход одного становится входом следующего — как трубопровод. Самые частые этапы: $match (фильтр), $group (группировка), $sort (сортировка).

Пусть есть коллекция заказов:

{ "_id": "o1", "city": "Казань", "total": 1800, "status": "paid" }
{ "_id": "o2", "city": "Казань", "total": 500,  "status": "paid" }
{ "_id": "o3", "city": "Москва", "total": 2200, "status": "paid" }

$match — отобрать нужное

$match работает как фильтр find: пропускает дальше только подходящие документы. Его ставят в начало, чтобы дальше по конвейеру шло меньше данных:

db.orders.aggregate([
  { $match: { status: "paid" } }
])

$group — сгруппировать и посчитать

Сердце агрегации. Поле _id внутри $group задаёт, по чему группируем (это не _id документа!), а остальные поля — что вычислить по группе. Сумма заказов по городам:

db.orders.aggregate([
  { $match: { status: "paid" } },
  { $group: {
      _id: "$city",
      revenue: { $sum: "$total" },
      orders:  { $sum: 1 }
  } }
])

Запись "$city" с долларом — это ссылка на значение поля city. $sum: "$total" складывает суммы заказов, $sum: 1 считает количество документов в группе. Результат:

Результат:

[
  { "_id": "Казань", "revenue": 2300, "orders": 2 },
  { "_id": "Москва", "revenue": 2200, "orders": 1 }
]

$sort — упорядочить итог

Результат группировки можно отсортировать — например, по выручке от большей к меньшей:

db.orders.aggregate([
  { $match: { status: "paid" } },
  { $group: { _id: "$city", revenue: { $sum: "$total" } } },
  { $sort: { revenue: -1 } }
])

Параллель с SQL

Конвейер легко читается через SQL: $match — это WHERE, $groupGROUP BY с агрегатными функциями, $sortORDER BY. Разница в том, что этапы выстраиваются явной цепочкой, и порядок этапов важен — $match до $group экономит работу.

Итог

  • Агрегация — это конвейер этапов; выход одного этапа поступает на вход следующего.
  • $match фильтрует (как WHERE), $group группирует и считает (как GROUP BY), $sort упорядочивает.
  • В $group поле _id — это ключ группировки; "$поле" ссылается на значение поля.
Проверьте себя
1. Что такое конвейер агрегации в MongoDB?
AОдин большой запрос find
BПоследовательность этапов, где выход одного становится входом следующего
CСпособ создания индексов
DФормат экспорта данных
2. Что задаёт поле _id внутри этапа $group?
AИдентификатор документа результата
BКлюч, по которому документы группируются
CИмя коллекции
DСлучайное значение
3. Какому SQL-оператору соответствует этап $match?
AORDER BY
BGROUP BY
CWHERE
DJOIN
Поддержать проект