Работа с внешними ключами в MongoDB: советы и методы
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
MongoDB не поддерживает механизм внешних ключей в классическом их понимании. В качестве замены обычно используются так называемые ручные ссылки, которые создают связи между документами в разных коллекциях.
В качестве примера можно привести отношение, где ObjectID документа хранится как ссылка в другом документе:
// Документ пользователя в коллекции "users"
{ "_id": ObjectId("user123"), "name": "Джон Доу" }
// Документ заказа в коллекции "orders", связанный с пользователем Джон Доу
{ "product": "Виджет", "quantity": 1, "user_id": ObjectId("user123") }
Для реализации соединений, аналогичных тем, что используются в SQL, в MongoDB рекомендуется использовать оператор $lookup
:
db.orders.aggregate([
{ $lookup: {
from: "users",
localField: "user_id", // поле с ID пользователя в "orders"
foreignField: "_id", // поле с ID пользователя в "users"
as: "userDetails" // псевдоним для результата соединения
}}
])
Таким образом можно имитировать отношения между сущностями, однако автоматическую целостность связей это не гарантирует. За все отвечает логика вашего приложения.
Стратегии моделирования данных
В MongoDB процесс создания модели данных зависит от следующих принципов:
Денормализация: Ускоряет чтение и упрощает запросы за счет включения связанных данных непосредственно в документ.
Ручные ссылки: Обеспечивают связь между документами с помощью массивов ObjectID, предлагая таким образом гибкий подход к управлению схемами.
Денормализация против ссылок: В этом вопросе всегда есть баланс. Отношения "один ко многим" в большинстве случаев предпочтительнее реализовывать с использованием внедренных документов, в то время как отношения "один к миллионам" требуют ручных ссылок.
Операции изменения: MongoDB делегирует каскадные обновления и удаления на уровень приложения, что является особо важным в рамках интенсивных операций записи.
Проектирование схемы: Необходимо придерживаться "шести правил", предложенных MongoDB для эффективного проектирования схемы. Очень важной является принципиальная дилемма: включение документов или использование ссылок – решение должно быть осознанным.
ORM под прожекторами
Фреймворки ORM и ODM, такие как Mongoid, MongoMapper и Mongoose, упрощают управление соотношениями между данными:
В Mongoid: –
embeds_many
иembedded_in
обеспечивают создание встроенных документов. – Отношенияbelongs_to
иhas_many
реализуются аналогично тому, как они реализуются в SQL.В Mongoose: – С помощью метода Populate автоматически выполняется замена путей в документе на связанные данные. – Виртуальные поля могут служить реляционными связями и подгружать дополнительные данные.
Защита целостности данных на уровне приложения
Из-за отсутствия встроенных механизмов ограничений в MongoDB ответственность за поддержание целостности данных лежит на приложении:
Каскадные обновления: При удалении одного из документов все связанные с ним документы остаются без изменений, поэтому необходим контроль за "сиротскими" записями.
Согласованность: Для того чтобы данные были согласованы, необходимо ввести специальные функции и промежуточное программное обеспечение (middleware).
Некорректные ссылки: Приложение должно уметь очищать или воссоздавать связи, если связанные документы были удалены.
Масштабирование во внимание
Проблема создания связей между большим набором данных заключается в необходимости балансировать между использованием ссылок и денормализацией:
Производительность ссылок: Разрешение большого количества ссылок может привести к снижению производительности из-за увеличения нагрузки на выполнение запросов.
Затраты пространства при денормализации: Денормализация ускоряет чтение, но может усложнить хранение данных и поддержание их согласованности.
Продвинутые соглашения для ссылок
Для создания ссылок, помимо прямого использования ObjectID, MongoDB предлагает:
DBRef: Стандартизированный метод создания ссылок через поля
"$ref"
,"$id"
и"$db"
.Имитация DBRef: Создание ссылок, подобных DBRef, но без применения специфического типа DBRef, для большей гибкости.
Фреймворк агрегации: Для решения сложных задач используйте фреймворк агрегации для создания графов документов или манипулирования связанными данными.
Визуализация
Визуально MongoDB можно представить в виде архипелага островов 🏝️, на каждом из которых расположены домики 🏠 (документы).
Если в SQL мире внешние ключи создают прочные мосты между домиками на разных островах 🌉:
🏠 1 на Острове А = 🌉 -> 🏠 А на Острове В
То в MongoDB монолитных мостов нет, и вместо этого документы связываются схоже с ситуацией, когда лодки следуют за компасом 🚣:
С 🏝️ А = 🚣 -> на 🏝️ B
Такая гибкость в организации структуры данных требует обдуманного подхода к управлению связями.
Управление обновлениями и удалением данных
В MongoDB, где нет встроенных каскадных операций, целесообразно использовать следующие практики управления данными:
Пакетное обновление: Запустите обновления для всех связанных документов при изменении одного из них.
Логика транзакций: Можно использовать транзакционные возможности MongoDB для координирования изменений в нескольких коллекциях.
Хуки и Middleware: Реализация методов предварительной и последующей обработки помогает автоматизировать процедуры обновления и удаления связанных документов.
Производительность и оптимизация
Для оптимизации запросов в MongoDB рекомендуется:
Индексы: Создавайте индексы на полях, используемых для ссылок и в операциях
$lookup
. Это ускоряет выполнение запросов.Ключи шардинга: Правильно подобранные ключи шардинга обеспечивают горизонтальное масштабирование и уменьшают количество межшардовых запросов.
Профиль чтения/записи: Проектируйте схему данных, ориентируясь на особенности чтения и записи, которые характерны для вашего приложения.