В реляционных базах данных можно устанавливать внешние ключи, когда поля из одной таблицы ссылаются на поля в другой таблице. В MongoDB также можно устанавливать ссылки. Далее мы рассмотрим установку ссылок между коллекцией users, которая хранит пользователей, и коллекцией companies, которая хранит список компаний, в которых работают пользователи.
Ручная установка ссылок сводится к присвоению значения поля _id одного документа полю другого документа. Допустим, у нас могут быть коллекции, представляющие компании и работников, работающих в этих компаниях. Итак, сначала добавим в коллекцию companies документ представляющий компанию:
db.companies.insertOne({"_id" : "microsoft", year: 1974})
Теперь добавим в коллекцию users документ, который представляет работника. В этом документе будет поле company, представляющее компанию, где работает работник.
И очень важно, что в качестве значения для этого поля мы устанавливаем не объект company, а значение ключа _id
добавленного выше документа:
db.users.insertOne({name: "Tom", age: 28, company: "microsoft"})
Теперь получим документ из коллекции users:
user = db.users.findOne()
В данном случае имеется в виду, что выше добавленный элемент будет единственным в коллекции. Иначе надо сделать выборку по _id последнего добавленого документа.
После этого консоль выводит полученный документ. И теперь найдем ссылку на его компанию в коллекции companies:
db.companies.findOne({_id: user.company})
И если документ с таким идентификатором обнаружен, он отображается на консоли:
test> db.companies.insertOne({"_id" : "microsoft", year: 1974}) { acknowledged: true, insertedId: 'microsoft' } test> db.users.insertOne({name: "Tom", age: 28, company: "microsoft"}) { acknowledged: true, insertedId: ObjectId("62e427069fcbf14521ea012a") } test> user = db.users.findOne() { _id: ObjectId("62e427069fcbf14521ea012a"), name: 'Tom', age: 28, company: 'microsoft' } test> db.companies.findOne({_id: user.company}) { _id: 'microsoft', year: 1974 } test>
Используя функциональность DBRef, мы можем установить автоматическое связывание между документами. Посмотрим на примере применение данной функциональности. Вначале добавим новый документ в коллекцию companies:
google = db.companies.insertOne({name : "google", year: 1998})
Обратите внимание, что мы получаем результат добавления в переменную google.
При добавлении нового документа генерирует _id, которыймы можем получить с помощью свойства insertedId
результата функции.
Теперь создадим новый документ для коллекции users, у которого ключ company свяжем с только что добавленным документом google:
sam = ({name: "Sam", age: 25, company: { "$ref" : "companies", "$id" : google.insertedId}}) db.users.insertOne(sam)
И мы можем протестировать:
db.companies.findOne({_id: sam.company.$id})
test> google = db.companies.insertOne({name : "google", year: 1998}) { acknowledged: true, insertedId: ObjectId("62e427c29fcbf14521ea012b") } test> sam = ({name: "Sam", age: 25, company: { "$ref" : "companies", "$id" : google.insertedId}}) { name: 'Sam', age: 25, company: { '$ref': 'companies', '$id': ObjectId("62e427c29fcbf14521ea012b") } } test> db.users.insertOne(sam) { acknowledged: true, insertedId: ObjectId("62e427dc9fcbf14521ea012c") } test> db.companies.findOne({_id: sam.company.$id}) { _id: ObjectId("62e427c29fcbf14521ea012b"), name: 'google', year: 1998 } test>
Посмотрев на примере, теперь разберем организацию ссылок между документами. Для связывания с документом google использовалось следующее
выражение { "$ref" : "companies", "$id" : google.insertedId}
. Формальный синтаксис DBRef следующий:
{ "$ref" : название_коллекции, "$id": значение [, "$db" : название_бд ]}
Первый параметр $ref указывает на коллекцию, где хранится связанный документ. Второй параметр указывает на значение, которое и будет представлять что-то типа внешнего ключа. Третий необязательный параметр указывает на базу данных.
При тестировании в качестве запроса на выборку указывается выражение _id: sam.company.$id
. Так как sam.company
представляет теперь объект { "$ref" : "companies", "$id" : google.insertedId}
, то нам надо конкретизировать параметр sam.company.$id