В прошлом уроке мы закончили моделирование: данные разложены, коллекции защищены правилами. Теперь по этим данным хочется считать. Сколько книг каждого жанра? Какая средняя цена? Кто из покупателей заказывает чаще всех? find на такие вопросы не отвечает: он возвращает документы, а не итоги. Итоги считает конвейер агрегации. Примеры идут на учебной базе магазина.
Сортировочная линия
Представь сортировочный центр почты. Посылки едут по ленте мимо нескольких постов. На первом посту отбрасывают всё, что не в Москву. На втором раскладывают оставшееся по районам и считают коробки в каждом. На третьем выстраивают районы по числу коробок. Каждый пост получает то, что отдал предыдущий, и делает одно простое действие.
Конвейер агрегации устроен так же. Это массив этапов, и документы коллекции проходят их по очереди:
books ─▶ $match ─▶ $group ─▶ $sort ─▶ результат
отбор итоги порядок
Запускает конвейер метод aggregate:
db.коллекция.aggregate([
{ этап1 },
{ этап2 },
...
])
$group: итоги по группам
Начнём с главного этапа. $group раскладывает документы по группам и для каждой группы выдаёт один документ с итогами. Сколько книг каждого жанра:
db.books.aggregate([
{ $group: { _id: '$genre', books: { $sum: 1 } } },
{ $sort: { books: -1, _id: 1 } }
])
[
{ _id: 'повесть', books: 3 },
{ _id: 'роман', books: 2 },
{ _id: 'учебник', books: 2 },
{ _id: 'фантастика', books: 2 }
]
Разберём, что написано в $group:
_id: '$genre'говорит, по чему группировать. Знак доллара перед именем поля значит «возьми значение этого поля из документа». Без доллара'genre'была бы обычной строкой, и все книги попали бы в одну группу с именемgenre.books: { $sum: 1 }это новое поле в выходном документе. Аккумулятор$sumприбавляет единицу за каждый документ группы, то есть считает документы.
Порядок групп после $group сервер не обещает, поэтому дальше стоит $sort. Второй ключ _id: 1 разводит жанры с одинаковым числом книг по алфавиту.
Если ты прошёл урок про агрегаты в PostgreSQL, этот запрос тебе знаком:
SELECT genre AS _id, count(*) AS books
FROM books
GROUP BY genre
ORDER BY books DESC, genre;
урок из курса
Урок из курса «MongoDB с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.