Проектируем схему: блог и магазин
Собираем всё вместе: проектируем реальные схемы, осознанно выбирая встраивание и ссылки.
Хорошая схема MongoDB начинается не с сущностей, а с вопроса: какие запросы будут чаще всего?
Кейс 1. Блог
Сущности: пользователи, посты, комментарии, теги. Подумаем о запросах: чаще всего открывают пост и сразу видят его текст, автора и комментарии. Значит:
- Комментарии встраиваем в пост — их немного и читаются они всегда вместе с постом.
- Автора — ссылкой (
authorId), но имя денормализуем в пост, чтобы лента не делала$lookup. - Теги — массив строк прямо в посте, по нему легко искать и индексировать.
{
"_id": "p1",
"title": "Знакомство с MongoDB",
"body": "...",
"authorId": "u1",
"authorName": "Анна",
"tags": ["mongodb", "nosql"],
"comments": [
{ "author": "Борис", "text": "Спасибо!", "at": "2026-01-10" }
]
}Лента постов по тегу — один индексированный запрос, без объединений:
db.posts.createIndex({ tags: 1 })
db.posts.find({ tags: "mongodb" }).sort({ _id: -1 })Кейс 2. Интернет-магазин
Сущности: товары, пользователи, заказы. Запросы: каталог товаров, история заказов пользователя, карточка заказа. Решения:
- Товары — отдельная коллекция: они переиспользуются во многих заказах, у них своя жизнь (цена, остаток).
- Заказ ссылается на пользователя (
userId) — заказов у пользователя может быть сколько угодно. - Позиции заказа встраиваем в заказ, причём с копией цены и названия на момент покупки — это денормализация ради истории: даже если цена товара потом изменится, в заказе останется та, по которой купили.
{
"_id": "ord-100",
"userId": "u1",
"createdAt": "2026-02-01",
"status": "paid",
"items": [
{ "sku": "SKU-1", "name": "Кофе", "price": 450, "qty": 2 },
{ "sku": "SKU-2", "name": "Чай", "price": 300, "qty": 1 }
],
"total": 1200
}История заказов пользователя — обычный запрос со ссылкой и индексом по userId:
db.orders.createIndex({ userId: 1, createdAt: -1 })
db.orders.find({ userId: "u1" }).sort({ createdAt: -1 })Логика принятия решений
Заметьте закономерность. Встраивали то, что принадлежит родителю и читается вместе с ним (комментарии, позиции заказа). Ссылались на то, что живёт самостоятельно и переиспользуется (пользователи, товары). Денормализовали стабильные данные ради скорости частых запросов (имя автора, цена на момент покупки). Это и есть документное проектирование — от запросов к структуре.
Итог
- Проектирование начинают с частых запросов, а не со списка сущностей.
- Встраивают принадлежащее и совместно читаемое; ссылаются на самостоятельное и переиспользуемое.
- Денормализуют стабильные данные (имя автора, цену на момент покупки) и индексируют поля частых фильтров.