top of page

Як працює агрегація в MongoDB: практичний гайд

Оновлено: 31 лип.

ree

MongoDB — це документо-орієнтована NoSQL база, оптимізована для роботи з даними, які мають складну структуру і можуть змінюватися з часом. Її використовують у Strum — найбільшій навчальній платформі в Genesis. Там MongoDB обслуговує понад 30 000 користувачів і дає змогу масштабовано працювати з навчальними курсами, прогресом, ролями та правами доступу. 


Один із ключових інструментів для аналітичних запитів у MongoDB — агрегація. Вона дозволяє не лише шукати документи за умовами, а й трансформувати, групувати та обчислювати метрики безпосередньо на рівні бази. У цьому тексті Сергій Бодров, Software Engineer в Genesis, пояснює High Bar Journal, як влаштований агрегаційний пайплайн MongoDB, як працюють основні етапи та оператори, та наводить приклади, як вони комбінуються. 



sergii-bodrov-software-engineer-genesis

Для наочності уявімо, що ми працюємо з колекцією фільмів. Кожен документ містить інформацію про назву, жанр, режисера, акторський склад, рейтинг, бюджет і касові збори. На цих прикладах ми розберемо, як працюють фільтрація, трансформації та групування в MongoDB.


mongodb-infographic


Агрегаційний пайплайн: як дані проходять через MongoDB


Агрегація в MongoDB — це механізм багатоступеневої обробки даних, який дозволяє послідовно трансформувати документи з колекції для досягнення конкретного результату: формування аналітичного звіту, зміни структури документів або об'єднання інформації з різних джерел.


На відміну від простих запитів find(), які лише повертають документи за умовою, агрегація дозволяє:


  • будувати умовну логіку;

  • змінювати структуру документа;

  • працювати з вкладеними масивами;

  • об’єднувати дані з різних колекцій;

  • знаходити суми, середні, мінімальні та максимальні значення.


У MongoDB агрегація будується у вигляді пайплайну — послідовності етапів, які обробляють документи з колекції. Кожен етап — це окремий об'єкт у масиві, що описує трансформацію, фільтрацію, обчислення або зміну структури. Усе це виконується всередині методу aggregate().


Уявіть пайплайн як конвеєр: документи колекції потрапляють на вхід, і на кожному етапі їх можна фільтрувати, змінювати або групувати. Наприклад:


  • $match — фільтрація документів;

  • $project — відбір або перейменування полів;

  • $unwind — розгортання масивів у кілька документів;

  • $group, $set, $replaceWith — інші трансформації, які будемо розглядати далі.


mongodb-aggregation-infographic

Пайплайн завжди повертає масив документів.


Для побудови та налагодження агрегаційних запитів зручно використовувати MongoDB Compass — графічний інтерфейс, який підтримує:


  • покрокову візуалізацію етапів пайплайну;

  • попередній перегляд результатів на кожному кроці;

  • зручне редагування та дебаг запитів.


Ті самі команди працюють і в Mongo Shell, і у всіх офіційних драйверах MongoDB — наприклад, у Node.js, Python, Java тощо.


У Strum агрегації активно застосовуються для розрахунку прогресу користувачів, формування списку доступних курсів і занять, побудови аналітичних звітів. Вони значно гнучкіші за базові методи find, updateOne чи deleteOne.


Також у пайплайні можна звертатися до системних змінних, зокрема:


  • $$NOW — повертає нинішню дату, яка лишається незмінною протягом усієї агрегації; 

  • $$ROOT — повертає чинний документ, часто використовується на етапі $group;

  • $$REMOVE  — видаляє поле з документа, часто використовується усередині оператора $cond для умовного видалення полів.


Поширені етапи агрегації: $set, $match, $project, $lookup, $group, $unwind, $sort, $replaceWith, $merge, $unset, $facet, $limit.


Також на STRUM використовуються: $skip, $bucket, $sample, $densify, $documents, $setWindowFields. 



Робота з полями: $project, $set


Етапи $project і $set використовуються тоді, коли потрібно змінити структуру кожного документа окремо — прибрати, залишити, додати або перезаписати поля. 


$project дозволяє залишити лише вибрані поля. Якщо якесь поле не вказане — воно буде вилучене. $set додає нові поля до документа або оновлює ті, що існують. Якщо ім’я поля збігається з наявним — значення буде перезаписано.


До прикладу, в документі залишимо тільки назву фільму, ім’я режисера та касові збори:


agregation-mongodb-project

Або сформуємо нові поля: округлимо рейтинг до найближчого цілого числа й порахуємо прибуток:


agregation-mongodb-set

Логічні, математичні, умовні оператори


Етапи $project і $set підтримують обчислення значень «на льоту» за допомогою агрегаційних операторів. Вони складаються з операторів, які записуються у форматі польської нотації: спочатку назва оператора, потім двокрапка і масив аргументів. Нижче — найуживаніші групи таких операторів.


1. Логічні оператори


  • $eq, $ne — перевірка на рівність або нерівність;

  • $gt, $lt, $gte, $lte — більше / менше / більше або дорівнює / менше або дорівнює; 

  • $in, $nin — перевірка, чи міститься / не міститься значення в масиві;

  • $not — логічне НІ;

  • $and, $or — логічне І / АБО для кількох умов.


Такі вирази завжди повертають true або false і використовуються для умовної логіки прямо всередині агрегаційного пайплайну.


2. Математичні оператори


  • $add, $subtract, $multiply, $divide — базові арифметичні операції;

  • $round — округлення числа до вказаного розряду.


Наприклад, додамо до цього документу два поля: чи містить список жанрів драму, чи окупився фільм (gross був більшим, ніж budget).


agregation-mongodb-math

3. Умовні оператори


Умовні оператори в MongoDB мають специфічний синтаксис. Один із найвживаніших — це $cond, який працює як тернарний оператор: приймає три аргументи — умову, результат при true, результат при false: { $cond: { if: умова, then: результат, else: результат } }.


Ще один приклад — $ifNull, який повертає перший визначений вираз з переданого масиву. Якщо перше null або його взагалі немає, Mongo візьме наступне. І тут ще один підводний камінь: у MongoDB null і відсутнє поле (undefined) трактуються однаково, що може призвести до несподіваної поведінки в складних пайплайнах.


Наприклад, спробуємо категоризувати фільми як «Blockbuster» або «Regular» залежно від прибутку:


agregation-mongodb-if-cond

Цей підхід дозволяє додавати умовну бізнес-логіку просто в агрегаційний пайплайн.



Оператори для роботи з масивами


MongoDB дозволяє безпосередньо працювати з масивами всередині документів — діставати окремі елементи, шукати значення, фільтрувати або трансформувати в нову структуру. Для цього є спеціальні оператори:


  • $arrayElemAt — повертає елемент масиву за заданим індексом; 

  • $indexOfArray — повертає індекс вказаного значення в масиві;

  • $size — повертає кількість елементів у масиві.


agregation-mongodb-elem-at

$filter — залишає лише ті елементи масиву, які відповідають умові. Наприклад, прибрати з масиву жанр «drama».


$map — трансформує кожен елемент масиву. Наприклад, залишити лише імена акторів із поля cast, де кожен актор — обʼєкт.


agregation-mongodb-filter-map

У виразах $map і $filter для звернення до поточного елемента масиву слід використовувати змінну $$this.


Наприклад, витягнемо ролі Метью Макконагі:


agregation-mongodb-task

Інші оператори:


  • $reduce — перетворення масиву на скаляр;

  • $arrayToObject — перетворення масиву на обʼєкт;

  • $concat — конкатенація рядків;

  • $mergeObjects — злиття обʼєктів;

  • $concatArrays — конкатенація масивів;

  • $toUpper / $toLower — приведення до регістра;

  • $setUnion — обʼєднання множин;

  • $slice — отримання підмножини масиву;

  • $setIntersection — перетин множин;

  • $switch — багатоваріантне гілкування;

  • $sortArray — сортування масиву;

  • $zip — транспонування двовимірного масиву.


Серед них уваги заслуговує $replaceWith, який повністю замінює документ. Наприклад, щоб замість всього документа лишити лише піддокумент director. Цей етап буквально викидає «обгортку» документа й залишає лише вказане поле або піддокумент.



Етапи, що змінюють структуру потоку документів


MongoDB має три ключові етапи агрегації, які змінюють структуру потоку документів: $match, $group і $unwind. 



$match


Етап $match виконує фільтрацію документів за заданою умовою. Синтаксис $match ідентичний синтаксису, який вживається у методах findOne і find. Оператор вказується після імені поля, наприклад: { year: { $gte: 2000 } }.


Умовні оператори на етапі $match:


  • { $eq: expr } / { $ne: expr } перевіряє, чи поле рівне / не рівне виразу;

  • { $gt: expr } / { $lt: expr } перевіряє, чи поле більше / менше за вираз;

  • { $in: array } / { $nin: array } перевіряє, чи поле міститься / не міститься у масиві;

  • { $gte: expr } / { $lte: expr } перевіряє, чи поле ≥ / ≤ за вираз;

  • { $exists: boolean } перевіряє, чи присутнє поле в документі;

  • { $size: int } перевіряє, чи рівний розмір поля-масиву числу;

  • { $regex: regex } перевіряє, чи задовольняє поле regex-виразу;

  • { $type: string } перевіряє, чи має поле певний тип.


Наприклад, залишимо в результаті лише ті документи, які задовольняють двом умовам: жанри фільму містять 'Drama', а ім’я режисера закінчується на nolan (незалежно від регістру).


agregation-mongodb-match

$group


Етап $group використовується для групування документів за певним ключем. Він зводить усі документи групи до одного документа, обчислюючи зведені значення: суму, середнє, мінімум, максимум тощо. Наприклад, щоб згрупувати фільми за іменем режисера і порахувати кількість фільмів та середній рейтинг.


agregation-mongodb-group

Оператори, які можна використовувати:

  • $sum, $avg, $min, $max;

  • $first, $last;

  • $push — додає всі значення в масив;

  • $addToSet — додає лише унікальні значення в масив.



$unwind


Цей етап агрегації розгортає масив: з одного документа з масивом створює кілька документів — по одному на кожен елемент масиву. Його використовують, коли потрібно працювати з кожним елементом масиву окремо — наприклад, фільтрувати, групувати або рахувати їх.


Ці етапи часто комбінуються. Наприклад, щоб порахувати кількість фільмів у кожному жанрі або, щоб знайти кількість унікальних акторів у фільмах жанру «drama».


Так, етап $unwind розгортає масив жанрів у фільмах, увідповіднюючи кожному жанру окремий документ, а потім $group рахує кількість фільмів у кожному жанрі. «The Godfather» із двома жанрами дає два документи — для Crime і Drama, а «The Matrix», у якого жанри не вказані, буде включений до групи з _id: null завдяки параметру preserveNullAndEmptyArrays: true. У підсумку маємо підрахунок жанрів із урахуванням навіть відсутніх значень.


agregation-mongodb-unwind

Отже, все вищезазначене — не просто набір команд MongoDB. Це приклад того, як підходити до обробки даних послідовно й структуровано, будувати пайплайн крок за кроком: від фільтрації через $match, до трансформації полів через $set, роботи з масивами через $map і $filter, і до групування та розгортання документів.


Найважливіше — зрозуміти логіку: кожен етап перетворює дані, які надходять з попереднього. І в кінці ми завжди отримуємо масив об’єктів, сформований точно під завдання. Це дозволяє будувати аналітику, змінювати структуру даних без постобробки на стороні коду.


tg-button

© 2035 by Business Name. Made with Wix Studio™

bottom of page