Я только что наткнулся на этот вопрос и, хотя он старый, я подумал, что было бы полезно добавить пару возможностей, не упомянутых в приведенных ответах. Кроме того, за последние несколько лет ситуация немного изменилась, поэтому стоит подчеркнуть, что SQL и NoSQL становятся все ближе друг к другу.
Один из комментаторов высказал мудрое предостерегающее отношение: «если данные реляционные, используйте реляционные». Однако этот комментарий имеет смысл только в реляционном мире, где схемы всегда предшествуют приложению.
ОТНОСИТЕЛЬНЫЙ МИР: Структурируйте данные> Напишите приложение, чтобы получить его
NOSQL WORLD: Разработайте приложение> Соответственно структурируйте данные
Даже если данные являются реляционными, вариант NoSQL все же возможен. Например, отношения "один ко многим" вообще не проблема и широко освещаются в документации MongoDB.
РЕШЕНИЕ В 2015 ГОДУ ПРОБЛЕМЫ 2010 ГОДА
После публикации этого вопроса были предприняты серьезные попытки приблизить noSQL к SQL. Команда под руководством Янниса Папаконстантину из Калифорнийского университета (Сан-Диего) работает над FORWARD , реализацией SQL ++, которая вскоре может стать решением постоянных проблем, подобных той, что опубликована здесь.
На более практическом уровне выпуск Couchbase 4.0 означал, что впервые вы можете выполнять собственные JOIN в NoSQL. Они используют свой собственный N1QL. Это пример JOIN
из их руководств :
SELECT usr.personal_details, orders
FROM users_with_orders usr
USE KEYS "Elinor_33313792"
JOIN orders_with_users orders
ON KEYS ARRAY s.order_id FOR s IN usr.shipped_order_history END
N1QL позволяет выполнять большинство, если не все операции SQL, включая агрегирование, фильтрацию и т. Д.
НЕ ТАК НОВОЕ ГИБРИДНОЕ РЕШЕНИЕ
Если MongoDB по-прежнему является единственным вариантом, я хотел бы вернуться к своей точке зрения, что приложение должно иметь приоритет над структурой данных. Ни в одном из ответов не упоминается гибридное встраивание, при котором большинство запрашиваемых данных внедряются в документ / объект, а ссылки сохраняются в меньшинстве случаев.
Пример: может ли ждать информация (кроме имени роли)? может ли загрузка приложения быть быстрее, если не запрашивать ничего, что пользователю еще не нужно?
Это может произойти, если пользователь входит в систему и ему / ей нужно увидеть все параметры для всех ролей, к которым он / она принадлежит. Однако пользователь является «инженером», и варианты для этой роли используются редко. Это означает, что приложение должно отображать параметры только для инженера, если он / она захочет по ним щелкнуть.
Это может быть достигнуто с помощью документа, который сообщает приложению в начале (1), к каким ролям принадлежит пользователь и (2) где получить информацию о событии, связанном с конкретной ролью.
{_id: ObjectID(),
roles: [[“Engineer”, “ObjectId()”],
[“Administrator”, “ObjectId()”]]
}
Или, что еще лучше, проиндексируйте поле role.name в коллекции ролей, и вам, возможно, также не потребуется встраивать ObjectID ().
Другой пример: информация обо всех запрошенных ролях ВСЕГДА?
Также может быть случай, когда пользователь входит в панель управления и 90% времени выполняет задачи, связанные с ролью «Инженер». Гибридное встраивание может быть выполнено для этой конкретной роли полностью, а ссылки сохранены только для остальных.
{_id: ObjectID(),
roles: [{name: “Engineer”,
property1: value1,
property2: value2
},
[“Administrator”, “ObjectId()”]
]
}
Отсутствие схемы - это не просто характеристика NoSQL, в этом случае это может быть преимуществом. Совершенно верно вкладывать различные типы объектов в свойство «Roles» пользовательского объекта.