Работа с отношениями данных в MongoDB
Как MongoDB обрабатывает отношения между документами? Используйте это руководство и примеры, чтобы узнать больше.
MongoDB — это база данных документов, которая не поддерживает связи между документами, как реляционные базы данных, такие как PostgreSQL.
Тем не менее, MongoDB позволяет создавать связи между документами. Эти отношения могут быть смоделированы с помощью встроенных или ссылочных подходов. Давайте посмотрим поближе.
Встроенные отношения против ссылочных отношений
При внедренном подходе документ непосредственно вставляется внутрь другого документа, в результате чего образуются вложенные данные. Этот процесс еще называют «денормализацией».
Ссылочный подход, с другой стороны, использует ссылки на документы для указания от одного документа к другому. Этот подход еще называют «нормализацией».
MongoDB: отношения «один к одному» со встроенными документами
Вы можете создать связь «один к одному» между документами, используя встроенный подход. Эта связь возникает, когда один объект документа может относиться только к одному другому документу.
Рассмотрим базу данных студентов. Эта база данных содержит коллекции студентов и адресов со следующими документами.
// Student Document
{
"studentName": "Frodo Baggins",
"phoneNumber": "987654321",
};
// Address Document
{
"studentName": "Frodo Baggins",
"street": "Bagshot Row",
"city": "Hobiton",
}
В этой базе данных студенту разрешено иметь только один адрес. Чтобы получить адрес, вам необходимо запросить коллекцию адресов, используя имя учащегося.
В тех случаях, когда адрес используется вместе с другими данными, такими как studentName, вам придется выполнить запрос к базе данных несколько раз. Обратной стороной этого является большое количество операций чтения и, как следствие, низкая производительность запросов.
Используя встроенный подход, вы можете вставить данные адреса прямо в документ студента и использовать только один запрос для получения данных.
{
"studentName": "Frodo Baggins",
"phoneNumber": "987654321",
"address": [{
"street": "Bagshot Row",
"city": "Hobiton"
}],
};
Чтобы получить адрес через studentName, используйте этот запрос.
db.student.findOne({"studentName":"Frodo Baggins"}, {"address":1})
Отношения «один ко многим» со встроенными документами в MongoDB
Рассмотрим ситуацию, когда у студента есть несколько адресов. Связь между студентом и адресами становится «один ко многим».
Встроенная модель позволяет добавлять в документ студента несколько адресов. Как и в случае отношений «один к одному» с использованием встроенных документов, этот подход имеет относительно высокую производительность запросов.
{
"studentName": "Frodo Baggins",
"phoneNumber": "987654321",
"address": [
{
"street": "Bagshot Row",
"city": "Hobiton"
},
{
"street": "Another Bagshot Row",
"city": "Hobiton2"
},
]
};
Запрос ниже вернет адреса указанного имени учащегося.
db.student.findOne({studentName: “Frodo Baggins”}, {address: 1})
Теперь, если у вас есть больше адресов и вы продолжаете добавлять их в поле адреса, документ может довольно быстро захламиться. Одним из решений является использование ссылок на документы.
MongoDB: отношения «один ко многим» со ссылками на документы
Вы также можете смоделировать связь «один ко многим», используя эталонный подход. В этой модели данных данные об учащихся и адресах будут храниться в отдельных коллекциях. Чтобы связать учащегося с его адресом, добавьте в документ учащегося поле, содержащее идентификаторы адреса.
{
"studentName": "Frodo Baggins",
"phoneNumber": "987654321",
"address": [
ObjectId("61fa7bfeebdadf8ac71427ea"),
ObjectId("61fa7d19ebdadf8ac71427eb")
]
};
Получение сведений об адресе учащегося включает в себя получение идентификаторов адресов из документа учащегося и использование этих идентификаторов для извлечения фактических адресов из коллекции.
const student = db.users.findOne({"name":"Frodo Baggins"},{"address":1})
const addresses = db.address.find({"_id":{"$in":student["address_ids"]}})
Выбор между встроенным и эталонным подходами
И у модели внедрения, и у модели ссылок есть свои плюсы и минусы, и вам придется принять во внимание несколько вещей, прежде чем сделать выбор. . Для начала вам необходимо рассмотреть вариант использования. Если данные будут связаны только с одним документом, лучшим вариантом будет встраивание.
Чтобы создать связи «один ко многим», вы можете использовать либо ссылочную модель, либо встроенную модель. Ссылка приводит к созданию чистого и единообразного документа, поскольку вы добавляете только идентификатор ссылки документа, к которому хотите обратиться.
Однако количество операций чтения, необходимых для получения подключенных данных, относительно велико и может повлиять на производительность. Внедрение документа может повысить производительность, но при наличии большого количества вложенных документов коллекция может оказаться перегруженной.
Таким образом, выбор способа реализации отношений данных в вашем документе полностью зависит от вас. Подумайте, как вы будете использовать документ, к какому уровню производительности запросов вы стремитесь и на какие компромиссы вы готовы пойти.