Конвейер агрегации: $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, $group — GROUP BY с агрегатными функциями, $sort — ORDER BY. Разница в том, что этапы выстраиваются явной цепочкой, и порядок этапов важен — $match до $group экономит работу.
Итог
- Агрегация — это конвейер этапов; выход одного этапа поступает на вход следующего.
$matchфильтрует (какWHERE),$groupгруппирует и считает (какGROUP BY),$sortупорядочивает.- В
$groupполе_id— это ключ группировки;"$поле"ссылается на значение поля.