ЛЕКЦІЯ 19

MongoDB: агрегація та індекси

Основи баз даних

VTFK • 2025

Що вже вивчили

Лекція 18: GROUP BY & Window Functions

  • GROUP BY для агрегації
  • HAVING для фільтрування
  • Віконні функції (ROW_NUMBER, LAG/LEAD)

План лекції

  • MongoDB aggregation pipeline
  • Етапи: $match, $group, $sort
  • Індекси в MongoDB
  • Оптимізація запитів

Фокус: аналіз даних у NoSQL

Aggregation pipeline

Aggregation Pipeline

Pipeline

Послідовність етапів, кожен з яких трансформує документи для отримання результату.

Аналогія: Як конвеєр на фабриці: дані проходять через фази

Pipeline етапи

Послідовність обробки

%%{init: {"theme": "neutral", "mermaid": {"version": "11.12.2"}}}%% flowchart LR Raw[Сирі документи
100] --> Match[{$match}] Match -->|30 документи| Group[{$group}] Group -->|3 групи| Sort[{$sort}] Sort -->|3| Limit[{$limit}] Limit --> Result[Результат
2 документи]

Основні операції pipeline

Операція Назва Приклад
$match Фільтр {$match: {age: {$gt: 25}}}
$group Агрегація {$group: {_id: '$country', count: {$sum: 1}}}
$sort Сортування {$sort: {count: -1}}
$limit Обмеження {$limit: 10}
$project Вибір полів {$project: {name: 1, age: 1}}
$lookup JOIN {$lookup: {from: 'orders', ...}}

Простий pipeline

Користувачи по країнах

db.users.aggregate([
  // Етап 1: Фільтр
  { $match: { active: true } },
  
  // Етап 2: Групування
  {
    $group: {
      _id: '$country',
      count: { $sum: 1 },
      avg_age: { $avg: '$age' }
    }
  },
  
  // Етап 3: Сортування
  { $sort: { count: -1 } },
  
  // Етап 4: Обмеження
  { $limit: 5 }
]);

Індекси в MongoDB

Створення індексів

Додаємо індекси

// Простий індекс
db.users.createIndex({ email: 1 });

// Descending
db.orders.createIndex({ created_at: -1 });

// Композитний індекс
db.orders.createIndex({ user_id: 1, created_at: -1 });

// Унікальний індекс
db.users.createIndex({ email: 1 }, { unique: true });

// Текстовий індекс
db.posts.createIndex({ title: 'text', content: 'text' });

Типи індексів

$lookup - JOIN у MongoDB

Об'єднання колекцій

db.orders.aggregate([
  {
    $lookup: {
      from: 'users',
      localField: 'user_id',
      foreignField: '_id',
      as: 'user_info'
    }
  },
  { $unwind: '$user_info' },  // розгорнути масив
  {
    $project: {
      order_id: '$_id',
      user_name: '$user_info.name',
      amount: 1
    }
  }
]);

Міні-вікторина

Який порядок операцій у pipeline найефективніший?

  • $limit → $match → $group
  • $match → $group → $limit
  • Порядок не важливий
✅ Правильна відповідь: $match → $group → $limit
💡 Пояснення:

$match спочатку зменшує документи, потім $group на менших наборах швидче.

Помилка: без індексів

⚠️ ЗАСТЕРЕЖЕННЯ

Повільні запити без індексів

❌ Неправильно

// Повільно: без індексу
db.users.find({ email: 'test@example.com' });  // full table scan

БД сканує кожний документ

✓ Правильно

// Швидко: з індексом
db.users.createIndex({ email: 1 });
db.users.find({ email: 'test@example.com' });  // index lookup

Індекс знаходить документ швидко

MongoDB еволюція

Від простого до складного

2009

Базові

insert/find/update/delete

2011

Aggregation

Первa версія pipeline

2014

Покращення

$lookup для JOIN

2025

AI-ready

Vector search вбудований

Best practices MongoDB

Міні ТЗ: Аналіз замовлень

Комплексний pipeline

З JOIN та агрегацією

db.orders.aggregate([
  { $match: { created_at: { $gte: new Date('2025-01-01') } } },
  { $lookup: { from: 'users', localField: 'user_id', foreignField: '_id', as: 'user' } },
  { $unwind: '$user' },
  { $group: { _id: '$user.name', total_spent: { $sum: '$amount' }, order_count: { $sum: 1 } } },
  { $sort: { total_spent: -1 } },
  { $limit: 10 },
  { $project: { _id: 1, total_spent: 1, order_count: 1 } }
]);

Підсумки

  • Pipeline етапи трансформують документи послідовно
  • Індекси критичні для продуктивності
  • $lookup об'єднує колекції (JOIN)

Далі — індекси у SQL

Домашнє завдання

Наступна лекція:

Лекція 20: Індекси

📚 Корисні ресурси:

📚 Корисні ресурси:

Дякую за увагу! 💾

← Повернутися до списку лекцій