MongoDB

Как MongoDB хранит модель, вложенную в другую модель

MongoDB может хранить модель, вложенную в другую модель, двумя основными способами: как вложенный документ внутри родительского документа или как отдельный документ со ссылкой через ObjectId. Если вложенные данные почти всегда читаются вместе с родителем, их удобно хранить внутри. Если вложенная модель живет отдельно, часто меняется или используется во многих местах, лучше использовать ссылку

Пример вложенного документа:

{
  name: "Dinar",
  profile: {
    city: "Sochi",
    role: "author"
  }
}

Здесь profile хранится прямо внутри пользователя

Вложенная модель в Mongoose

const profileSchema = new mongoose.Schema({
  city: String,
  role: String
});

const userSchema = new mongoose.Schema({
  name: { type: String, required: true },
  profile: profileSchema
});

Документ в MongoDB будет выглядеть примерно так:

{
  _id: ObjectId("..."),
  name: "Dinar",
  profile: {
    city: "Sochi",
    role: "author"
  }
}

Это удобно, если профиль не нужен отдельно от пользователя

Массив вложенных моделей

Например, у заказа есть позиции:

const orderItemSchema = new mongoose.Schema({
  title: String,
  price: Number,
  quantity: Number
});

const orderSchema = new mongoose.Schema({
  userId: mongoose.Schema.Types.ObjectId,
  items: [orderItemSchema],
  status: String
});

В MongoDB заказ будет хранить массив items внутри одного документа

Это удобно для заказа, потому что позиции обычно нужны вместе с заказом

Когда использовать ссылку

Если модель используется отдельно, лучше хранить ее в своей коллекции

const postSchema = new mongoose.Schema({
  title: String,
  author: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User"
  }
});

Получить автора можно через populate():

const post = await Post.findById(id).populate("author");

Так пользователь хранится отдельно, а статья содержит ссылку на него

Как выбрать подход

Вкладывайте, если данные маленькие, читаются вместе и не используются отдельно

Используйте ссылку, если данные большие, связаны со многими документами или должны обновляться независимо

Пример: адрес доставки в заказе можно вложить, потому что он фиксирует состояние на момент заказа. А автора статьи лучше хранить ссылкой, потому что один автор связан со многими статьями

Частые ошибки

Вкладывают бесконечно растущий массив

Комментарии, события или логи могут расти без ограничения. Такой массив лучше выносить в отдельную коллекцию

Делают ссылки там, где нужен снимок данных

В заказе часто лучше хранить название и цену товара на момент покупки, а не только ссылку на товар. Иначе после изменения товара старый заказ может выглядеть неверно

Путают вложенный документ и populate

populate() работает со ссылками через ObjectId. Для обычного вложенного объекта он не нужен

Короткий чек-лист

  1. Данные читаются вместе? Можно вложить.
  2. Данные нужны отдельно? Лучше ссылка.
  3. Массив может расти бесконечно? Лучше отдельная коллекция.
  4. Нужен исторический снимок? Часто лучше вложить копию.
  5. Нужна связь many-to-many? Обычно лучше ссылки и отдельная структура.

Что почитать дальше по MongoDB

Если нужен общий маршрут по теме, откройте рубрику MongoDB. Для соседних задач пригодятся эти разборы:

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x