aggregate в MongoDB нужен, когда обычного find() уже мало. Через aggregation pipeline можно фильтровать документы, группировать их, считать суммы, собирать статистику, менять форму результата и строить отчеты. Pipeline — это цепочка этапов: документ проходит через первый этап, затем через второй, третий и так дальше
Самая частая схема такая:
db.orders.aggregate([
{ $match: { status: "paid" } },
{ $group: { _id: "$userId", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
])
Этот запрос берет оплаченные заказы, группирует их по пользователю, считает сумму заказов и сортирует пользователей по общей сумме
Пример данных
Добавим несколько заказов:
db.orders.insertMany([
{ userId: 1, amount: 1200, status: "paid", city: "Sochi" },
{ userId: 1, amount: 800, status: "paid", city: "Sochi" },
{ userId: 2, amount: 1500, status: "new", city: "Moscow" },
{ userId: 2, amount: 2000, status: "paid", city: "Moscow" }
])
Теперь построим отчет по городам:
db.orders.aggregate([
{ $match: { status: "paid" } },
{
$group: {
_id: "$city",
ordersCount: { $sum: 1 },
totalAmount: { $sum: "$amount" }
}
},
{ $sort: { totalAmount: -1 } }
])
Результат покажет города, количество оплаченных заказов и общую сумму
Что делают основные этапы
$match фильтрует документы. Его часто ставят в начале, чтобы дальше pipeline обрабатывал меньше данных
{ $match: { status: "paid" } }
$group группирует документы и считает агрегаты:
{
$group: {
_id: "$city",
totalAmount: { $sum: "$amount" }
}
}
$project управляет тем, какие поля попадут в результат:
{
$project: {
_id: 0,
city: "$_id",
totalAmount: 1
}
}
$sort сортирует:
{ $sort: { totalAmount: -1 } }
Полный красивый пример
db.orders.aggregate([
{ $match: { status: "paid" } },
{
$group: {
_id: "$city",
ordersCount: { $sum: 1 },
totalAmount: { $sum: "$amount" }
}
},
{
$project: {
_id: 0,
city: "$_id",
ordersCount: 1,
totalAmount: 1
}
},
{ $sort: { totalAmount: -1 } }
])
Такой pipeline уже похож на реальный отчет для админки
Как использовать all в агрегации MongoDB
Если вам нужно выбрать документы, где массив содержит все нужные значения, в фильтре можно использовать $all:
db.products.aggregate([
{ $match: { tags: { $all: ["database", "backend"] } } }
])
Это вернет товары, у которых в tags есть оба значения
Частые ошибки
Поле в group написано без $
Нужно писать "$amount", а не "amount". Без $ MongoDB воспринимает значение как обычную строку
Слишком поздно поставили match
Если фильтр можно применить в начале, ставьте $match первым. Так pipeline обработает меньше документов
Потеряли поле после group
После $group остаются только _id и рассчитанные поля. Если нужное поле не добавили в group, дальше его уже не будет
Смешали find и aggregate
find() подходит для обычной выборки. aggregate() нужен для цепочки обработки и отчетов
Что почитать дальше по MongoDB
Если нужен общий маршрут по теме, откройте рубрику MongoDB. Для соседних задач пригодятся эти разборы:
- MongoDB install: как установить MongoDB и проверить первый запуск
- PyMongo: как подключить Python к MongoDB и выполнить первый CRUD
- Как правильно составить запрос в MongoDB
- Discord bot на Python и MongoDB: как задать проверку
Как проверить результат на практике
Для MongoDB-материала полезно делать три проверки: сначала выполнить команду на маленьком наборе тестовых документов, затем посмотреть результат через find() или MongoDB Compass, а после этого повторить действие на копии реальной структуры данных. Если запрос меняет документы, сначала запускайте его с фильтром на один документ и только потом расширяйте условие
Еще одна хорошая привычка — записывать исходное состояние и ожидаемый результат. Например: было три документа, после обновления изменился только один; был массив из пяти элементов, после операции остался нужный элемент; индекс появился в getIndexes(). Такая проверка быстро показывает, что вы исправили именно задачу, а не просто получили команду без ошибки



