Как применять внешние ключи в базах данных NoSql (MongoDB)?

Скажем, у меня есть набор документов, таких как:

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc

И, с другой стороны, владельцы представлены как отдельная коллекция:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"}

Как я могу убедиться, что когда я вставляю документ, он правильно ссылается на пользователя. В РСУБД старой школы это можно легко сделать с помощью внешнего ключа.

Я знаю, что я могу проверить правильность вставки из моего бизнес-кода, НО что, если злоумышленник заманивает мой запрос на сервер и ставит "владелец": 100, а Mongo не возвращает никаких исключений.

Я хотел бы знать, как эту ситуацию следует обрабатывать в реальном приложении.

Заранее благодарю вас!

Ответ 1

MongoDB не имеет внешних ключей (как вы, вероятно, заметили). В принципе, ответ заключается в следующем: "Не позволяйте пользователям вмешиваться в запросы. Только пусть приложение вставляет данные, которые следуют вашим правилам ссылочной целостности".

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

Ответ 2

Чтобы ответить на ваш конкретный вопрос - в то время как MongoDB поощряет обработку внешних ключей на стороне клиента, они также предоставляют идею "Ссылки на базы данных" - см. эту справочную страницу.

Тем не менее, я не рекомендую использовать DBRef. Либо пусть ваш клиентский код управляет ассоциациями или (еще лучше) связывает документы вместе с самого начала. Возможно, вы захотите рассмотреть вопрос о внедрении "документов" владельца внутри самого объекта-владельца. Соберите свои документы в соответствии с вашими шаблонами использования, и MongoDB будет сиять.

Ответ 3

Я также рекомендую, чтобы, если имя пользователя уникально, используйте их как _id. Вы сэкономите на индексе. В хранящемся документе установите значение "владелец" в приложении как значение "имя пользователя", когда документ создан, и никогда не позволяйте ему обновлять какой-либо другой код.

Если существуют требования по изменению владельца, то предоставите API-интерфейс с одобренными бизнес-правилами.

Там не понадобятся внешние ключи.

Ответ 4

Если кто-то действительно хочет принудительно использовать внешние ключи в Project/WebApp. Затем вы должны использовать подход MixSQL, то есть SQL + NoSQL

Я бы предпочел, чтобы объемные данные, которые не имеют таких ссылок, могут быть сохранены в базе данных NoSQL Store. Например: Тип данных "Отели или места".

Но если есть такие серьезные вещи, как OAuth modules Tables, TokenStore и UserDetails и UserRole (Таблица сопоставления) и т.д...., тогда вы можете пойти с SQL.

Ответ 5

Как решение NoSQL, вы можете использовать MariaDB (NewSQL) Его сочетание SQL и NoSQL и реализовано разработчиками MySQL с большой производительностью.

Ответ 6

Это взаимно-однозначное отношение. Лучше встроить один документ в другой, вместо того, чтобы поддерживать отдельные коллекции. Проверьте здесь о том, как моделировать их в mongodb и их преимуществах.

Хотя его явно не упоминается в документах, вложение дает тот же эффект, что и ограничения внешнего ключа. Просто хочу сделать эту идею понятной. Когда у вас есть две коллекции:

С1:

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc

С2:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"}

И если вы должны объявить ограничение внешнего ключа на C2._id ссылкой C1._id (если предположить, что MongoDB позволяет это), это означает, что вы не можете вставить документ в C2, где C2._id не существует в C1. Сравните это со встроенным документом:

{
    "_id" : 0 , 
    "owner" : 0,
    "name" : "Doc1",
    "owner_details" : {
        "username" : "John"
    }
}

Теперь поле owner_details представляет данные из коллекции C2, а остальные поля представляют данные из C1. Нельзя добавить поле owner_details в несуществующий документ. Вы, по сути, добиваетесь того же эффекта.