Как реализовать связи между коллекциями в MongoDB?

«Как реализовать связи между коллекциями в MongoDB?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, в MongoDB можно моделировать связи между сущностями, используя два основных подхода:

1. Встраивание (Embedding)

Данные хранятся внутри одного документа. Подходит для отношений «один-ко-многим» или «один-к-одному», когда связанные данные часто запрашиваются вместе и не растут бесконечно.

// Документ пользователя с встроенными адресами
{
  "_id": 1,
  "name": "John",
  "addresses": [
    { "type": "home", "street": "123 Main St", "city": "Boston" },
    { "type": "work", "street": "456 Office Ave", "city": "Cambridge" }
  ]
}

Плюсы: Атомарные чтение/запись, высокая производительность для связанных запросов. Минусы: Размер документа ограничен (16 МБ), сложно обновлять вложенные данные в многих документах.

2. Ссылки (Referencing)

Документы хранятся в разных коллекциях и связываются по ObjectId или другому ключу. Подходит для «многие-ко-многим» или когда связанные данные большие или часто обновляются независимо.

// Коллекция `users`
{ "_id": ObjectId("507f1f77bcf86cd799439011"), "name": "John" }

// Коллекция `orders`
{ 
  "_id": ObjectId("53f7f77bcf86cd799439022"),
  "product": "Laptop",
  "userId": ObjectId("507f1f77bcf86cd799439011") // Ссылка
}

Плюсы: Гибкость, нет ограничений на размер, нормализация данных. Минусы: Требует $lookup (аналог JOIN) для объединения, что может быть менее производительно.

Критерии выбора:

  • Используйте встраивание, если связь сильная, данные невелики и часто читаются вместе.
  • Используйте ссылки, если связь слабая, данные растут или обновляются независимо.