如何在NoSql数据库(MongoDB)中强制执行外键?

Ari*_*său 17 mongodb nosql

假设我有一些文档集合,例如:

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc
Run Code Online (Sandbox Code Playgroud)

而另一方面,业主被表示为一个单独的集合:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"}
Run Code Online (Sandbox Code Playgroud)

如何在插入文档时确保以正确的方式引用用户.在旧式RDBMS中,可以使用外键轻松完成.

我知道我可以从我的业务代码中检查插入的正确性,但是如果攻击者篡改我对服务器的请求并将"所有者":100放入,那么Mongo不会抛出任何异常.

我想知道如何在真实的单词应用程序中处理这种情况.

先感谢您!

mda*_*man 20

MongoDB没有外键(正如你可能已经注意到的那样).因此,基本上答案是"不要让用户篡改请求.只允许应用程序插入遵循参照完整性规则的数据."

MongoDB在很多方面都很棒......但是如果你发现你需要外键,那么它可能不是你问题的正确解决方案.


Set*_*thO 14

回答您的具体问题 - 当MongoDB鼓励在客户端处理外键关系时,他们也提供"数据库引用"的想法 - 请参阅此帮助页面.

也就是说,我不建议使用DBRef.让您的客户端代码管理关联或(更好)从一开始就将文档链接在一起.您可能需要考虑在所有者对象本身内嵌入所有者的"文档".组装您的文档以符合您的使用模式,MongoDB将大放异彩.


And*_*sin 5

这是一对一的关系。最好将一个文档嵌入到另一个文档中,而不是维护单独的集合。请在此处查看如何在 mongodb 中对它们进行建模及其优点。

尽管文档中没有明确提及,但嵌入可以提供与外键约束相同的效果。只是想把这个想法说清楚。当你有两个这样的集合时:

C1:

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc
Run Code Online (Sandbox Code Playgroud)

C2:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"}
Run Code Online (Sandbox Code Playgroud)

如果您要对引用C2._id声明外键约束C1._id(假设 MongoDB 允许),则意味着您无法将文档插入C2到. 将其与嵌入文档进行比较:C2._idC1

{
    "_id" : 0 , 
    "owner" : 0,
    "name" : "Doc1",
    "owner_details" : {
        "username" : "John"
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,owner_details 字段表示来自 C2 集合的数据,其余字段表示来自 C1 的数据。您无法将owner_details 字段添加到不存在的文档中。您基本上达到了相同的效果。

  • @StanislavKarakhanov,我认为这是一对一的关系!这个博客对我在 MongoDB 中建模一对多关系很有帮助 https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1 (2认同)