MongoDB — это не просто «база данных для JSON», а мощная платформа, где проектирование схемы и написание запросов требуют особого подхода. В отличие от реляционных БД, здесь нет жёсткой структуры, и это одновременно свобода и ловушка: неудачная модель данных или неоптимальный агрегационный конвейер могут превратить быстрый сервис в тормозящего монстра.
Я собрал 12 промтов, которые помогут вам выжать максимум из MongoDB. Они охватывают три уровня: базовый (проектирование схем и простые запросы), продвинутый (агрегации и оптимизация) и экспертный (индексы, анализ производительности, нетривиальные сценарии). Каждый промт можно скопировать и адаптировать под свою задачу.
Базовый уровень: проектирование схем и запросы
1. Проектирование гибкой схемы под ваши паттерны доступа
Задача: Спроектировать схему MongoDB, которая будет масштабироваться и не требовать частых миграций.
Промт:
Спроектируй схему MongoDB для [описание вашего приложения, например, "сервис управления задачами с тегами и комментариями"]. Учти: [перечислите требования, например, "частые запросы по статусу задачи, необходимость хранить историю изменений"]. Предложи структуру документов, выбери между встраиванием и ссылками, обоснуй решение. Укажи, какие поля следует индексировать.
Пример результата:
// tasks collection
{
"_id": ObjectId(),
"title": "Написать отчёт",
"status": "in_progress",
"tags": ["работа", "срочно"],
"assignee": ObjectId("..."), // ссылка на users
"comments": [
{ "user": ObjectId("..."), "text": "...", "created_at": ISODate(...) },
],
"history": [
{ "field": "status", "old": "todo", "new": "in_progress", "at": ISODate(...) }
],
"created_at": ISODate(...)
}
Индексы: {status: 1, assignee: 1}, {tags: 1}.
2. Написание запроса с условиями, сортировкой и проекцией
Задача: Получить данные с фильтрацией и сортировкой, не вытаскивая лишнего.
Промт:
Напиши MongoDB запрос (на языке [Python/pymongo, JS, mongo shell]) для коллекции [имя], который выбирает документы по [условие, например, "поле status равно 'active'"], сортирует по [поле, например, "created_at desc"], ограничивает количество до [N], и возвращает только поля [перечислить]. Объясни, как работает запрос.
Пример результата:
db.users.find(
{ status: "active", age: { $gte: 18 } },
{ name: 1, email: 1, _id: 0 }
).sort({ created_at: -1 }).limit(10)
3. Проектирование встраиваемых документов для связей «один-ко-многим»
Задача: Решить, когда встраивать массив (например, адресов) в документ, а когда выносить в отдельную коллекцию.
Промт:
Для связи "один-ко-многим" в MongoDB (например, пользователь и его заказы) объясни, когда лучше встроить массив в документ, а когда создать отдельную коллекцию. Приведи примеры для [ваш случай]. Учти размер данных, частоту доступа и атомарность операций.
Продвинутый уровень: агрегации и оптимизация
4. Написание aggregation pipeline для статистики
Задача: Посчитать количество заказов по статусам за последний месяц.
Промт:
Напиши aggregation pipeline для MongoDB, который из коллекции [orders] группирует документы по полю [status], фильтрует по дате (за последний [30] дней) и возвращает количество заказов в каждом статусе. Включи пояснение каждого этапа.
Пример результата:
db.orders.aggregate([
{ $match: { created_at: { $gte: new Date(new Date().setMonth(new Date().getMonth() - 1)) } } },
{ $group: { _id: "$status", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
5. Денормализация и $lookup для объединения коллекций
Задача: Получить заказы с информацией о пользователях.
Промт:
Используя $lookup, объедини коллекции [orders] и [users] для получения заказов с полями [name, email] пользователя. Напиши pipeline и объясни, какие ограничения есть у $lookup (например, производительность на больших коллекциях).
Пример результата:
db.orders.aggregate([
{ $lookup: {
from: "users",
localField: "user_id",
foreignField: "_id",
as: "user"
}},
{ $unwind: "$user" },
{ $project: { total: 1, "user.name": 1, "user.email": 1 } }
])
6. Использование условной логики в агрегации ($cond, $switch)
Задача: Присвоить заказам категории в зависимости от суммы.
Промт:
В aggregation pipeline добавь поле [category], которое вычисляется на основе [total]: если total > 1000, то 'large', если > 500 — 'medium', иначе 'small'. Используй $switch или $cond.
Пример результата:
db.orders.aggregate([
{ $addFields: {
category: {
$switch: {
branches: [
{ case: { $gt: ["$total", 1000] }, then: "large" },
{ case: { $gt: ["$total", 500] }, then: "medium" }
],
default: "small"
}
}
}}
])
7. Оптимизация aggregation pipeline: стадии и порядок
Задача: Сократить время выполнения тяжёлой агрегации.
Промт:
Как оптимизировать следующий aggregation pipeline? [вставьте ваш pipeline]. Подскажи, какие стадии можно выполнить раньше (например, $match до $group), где использовать $project для уменьшения объёма данных, и как проверить план выполнения через explain.
Экспертный уровень: индексы и тонкая настройка
8. Создание составных индексов для типичных запросов
Задача: Ускорить запросы, которые фильтруют по нескольким полям.
Промт:
Для коллекции [users] с частыми запросами по {status, created_at} спроектируй составной индекс. Объясни порядок полей в индексе и как он влияет на сортировку. Приведи пример создания индекса в pymongo или mongo shell.
Пример результата:
db.users.createIndex({ status: 1, created_at: -1 })
9. Поиск узких мест через explain
Задача: Понять, почему запрос выполняется медленно.
Промт:
Объясни, как использовать метод explain("executionStats") в MongoDB для анализа производительности запроса. Что означают ключевые показатели: totalDocsExamined, totalKeysExamined, executionTimeMillis? Приведи пример интерпретации результата для запроса [ваш запрос].
Пример результата:
db.collection.find({...}).explain("executionStats")
10. Использование TTL-индексов для автоматического удаления данных
Задача: Автоматически удалять сессии через 24 часа.
Промт:
Создай TTL-индекс в MongoDB для коллекции [sessions], чтобы документы автоматически удалялись через [24] часа после поля [created_at]. Объясни ограничения TTL (например, фоновая задача раз в 60 секунд) и дай пример создания.
Пример результата:
db.sessions.createIndex({ created_at: 1 }, { expireAfterSeconds: 86400 })
11. Партиционирование данных с помощью $lookup и $merge для аналитики
Задача: Построить витрину данных для аналитики.
Промт:
Спроектируй конвейер для периодического агрегирования данных из [orders] в отдельную коллекцию [daily_stats] с помощью $merge. Учти, что статистика должна обновляться ежедневно. Приведи пример pipeline и опиши, как настроить его запуск (например, через cron).
Пример результата:
db.orders.aggregate([
{ $match: { created_at: { $gte: startOfDay } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$created_at" } }, total: { $sum: "$amount" }, count: { $sum: 1 } } },
{ $merge: { into: "daily_stats", on: "_id", whenMatched: "replace" } }
])
12. Моделирование данных для MongoDB с учётом паттернов доступа
Задача: Спроектировать схему для сложного домена (например, интернет-магазин с корзиной и заказами).
Промт:
Спроектируй схему MongoDB для интернет-магазина: каталог товаров (с вариантами), корзина, заказы, пользователи. Учти: товары с большим количеством атрибутов, корзина должна быстро обновляться, заказы требуют транзакций. Предложи структуры документов, обоснуй выбор встраивания и ссылок, опиши, какие индексы нужны.
Итоги
Эти промты — не просто шаблоны, а отправные точки для решения реальных задач. Начните с базовых — они помогут избежать ошибок при моделировании. Переходите к агрегациям, когда нужно вытащить сложную статистику. И обязательно освойте explain — это ваш главный инструмент для поиска узких мест.
MongoDB постоянно развивается, поэтому следите за официальной документацией и практиками сообщества. Если вы хотите систематизировать знания и научиться применять такие промты на практике, загляните в наш курс по MongoDB. А пока — попробуйте эти промты на своих данных. Уверен, вы узнаете много нового о своей базе.
Комментарии