Возможно ли иметь связь между объектом в базе данных MongoDB?

Я использую MongoDB на работе в эти дни. До сих пор я нахожу это большим опытом.

Однако меня просят установить отношения между коллекциями с MongoDB. Это противоречит цели концепции NoSQL для меня, но, будучи хорошим старым noob в этой области, я пришел, чтобы попросить другие мнения.

Например, если мы возьмем общее отношение Роль/Пользователь, возможно ли иметь ссылочную коллекцию с именем "Роли" и присвоить ссылку одного элемента элементу пользователя?

Я начал думать о создании объекта, который предоставляет идентификатор запрашиваемому объекту, но он чувствует себя чем-то, что мне не нужно делать с NoSQL.

Так есть люди, которые просили сделать то же самое? Удалось ли вам и как?

Ответ 1

MongoDB (и большинство других баз данных NoSQL) не поддерживают концепцию отношений. RDBMSs имеют собственные инструменты запросов для определения и использования связей (например, JOINs), которых не хватает MongoDB.

Это не означает, что вы не можете определить отношения/ссылки в базах данных NoSQL. Это просто означает, что нет собственных операторов запросов, которые знают отношения.

Существует три разных способа "ссылаться" на один документ от другого в MongoDB:

  • Хранить идентификатор указанного документа (обычно ObjectId) в качестве поля в ссылочном документе. Это лучший подход, если ваше приложение будет знать, в какой коллекции он должен искать упомянутый документ. Example : {_id: ObjectId(...); userId: ObjectId(...) <- reference).

  • Второй подход - это использование соглашения DBRef, которое формализует ссылку на документ: { $ref : <collname>, $id : <idvalue>[, $db : <dbname>] }. Почти во всех случаях первый подход предпочтителен, но DBRef действительно позволяет ссылаться на документ, который может не знать тип или местоположение. Furhter здесь: http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef и хорошо читайте, когда их использовать здесь: http://valyagolev.net/article/mongo_dbref/

  • Технически не ссылка, но во многих случаях имеет смысл вставлять (части) документы в другие документы. Обратите внимание, что нормализация вашей схемы должна быть меньше фокуса с базами данных NoSQL. Example : {_id: ObjectId(...); user: {_id: ObjectId(...), name:"Willy Wonka"}}.

Все, что сказано, вы можете использовать полностью нормализованную схему в MongoDB, и большинство библиотек ORM сделают для вас много работы, которая не является родной для MongoDB. В большинстве случаев это означает, что вам будет лучше работать с традиционной RDBMS. Если вы переходите на MongoDB, потому что считаете его быстрой версией MySQL, вы были дезинформированы. Оба имеют функциональные sweetspots с ограниченным перекрытием. Если ваше приложение сильно зависит от реляционной функциональности, не используйте NoSQL.

Другие статьи, которые стоит прочитать, чтобы ускорить процесс нереляционного мышления: http://www.mongodb.org/display/DOCS/Schema+Design

Ответ 2

Я бы сделал это следующим образом:

db.permissions {
 "Admins" : { "Users" : ["Peter", "Tom"], "Privilages": "rw" },
 "Supervisors" : { "Users" : ["Tom", "Brad", "Angelina"], "Privilages": "w" },
 ...
}

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

Кроме того, вы можете просто сохранить $_id каждого члена в массиве "Пользователи" и иметь пользователей с их именами, телефоном и... в отдельной коллекции. Другой вариант - хранить пользовательские документы в массиве "Пользователи", но это может стать громоздким для администрирования.