MongoDB的外键约束的替代方案

9
我创建了一个SQL数据库并检查了完整性。现在我想把这些表放到mongoDB中,并将其保留在映射规则中。表=集合,行=文档等等。
但是,在mongoDB中如何进行以下操作:
create table pruefen 
( MatrNr integer references Studenten on delete cascade,
  VorlNr integer references Vorlesungen,  
  PersNr integer references Professoren on delete set null,  
  Note numeric(2,1) check (Note between 0.7 and 5.0),   
  primary key (MatrNr, VorlNr));

DBRef并不是外键的替代品,我尝试过但无法达到这个效果。

如果应用程序接管了,它会是什么样子?


12
你发现了NoSQL中的“No” ;) - Madbreaks
2个回答

29

MongoDB没有级联删除。当你的应用程序删除数据时,它也负责自行删除任何引用对象以及对已删除文档的所有引用。但通常在关系型数据库中使用on delete时,你拥有一个组合的情况,其中一个父对象拥有一个或多个子对象,而子对象没有父对象就毫无意义。在这种情况下,MongoDB鼓励嵌入而不是引用。这意味着你在父对象中创建一个数组,并将完整的子文档放入该数组中,而不是将它们保留在自己的集合中。这样,它们将随着父级一起被删除,因为它们是其一部分。

虽然在SQL中在字段中保留多个值绝对是不可以的,但在MongoDB中并没有任何问题。这是因为MongoDB查询语言可以轻松地处理数组和嵌入式对象。你甚至可以在数组的子文档字段上创建索引,因此你可以轻松搜索嵌套在其他对象中的对象。

当你仍然想从另一个集合引用对象时,你可以使用DBRef,或者你也可以使用任何其他唯一标识符(唯一性是MongoDB可以强制执行的少数几件事之一。为此,使用createIndex命令创建唯一索引)。但在这种情况下,MongoDB不会强制执行一致性。你可以创建指向不存在ObjectId的DBRefs,当DBRef所指向的文档被删除时,什么也不会发生。应用程序负责确保在删除文档时更新所有引用它的文档。

MongoDB也无法强制执行约束。由于MongoDB的无模式特性,它甚至无法强制执行字段的特定类型。同样,你的应用程序负责确保将数据放入MongoDB中遵循特定规范。如果想要自动化这一过程,许多编程语言都提供了面向对象的映射框架以用于MongoDB。

总之: MongoDB不像SQL数据库那样“聪明”。它不能自动完成太多事情。它只会按照应用程序的指示执行任务,不多也不少。但这正是它快速(没有昂贵的一致性检查)和灵活(不需要修改数据库以实现新功能)的原因。


1
"MongoDB鼓励嵌入而不是引用",您能提供链接吗? - Eddie Jamsession
1
在数据库层面强制执行约束不应该比在应用程序层面更快吗?这难道不意味着 MongoDB 最终会因此变得更慢吗?更不用说那些应用程序级别的约束将如何得到很好的实现了... - Tamas Hegedus
@TamasHegedus 在工作中使用正确的工具。如果你正在使用MongoDB,但尝试模拟SQL数据库中的每个功能,那么它肯定会变慢,因为你没有按照它设计的用例来使用它。 - Philipp

8

关于关系型数据库的其中一个优点就是它能够在数据库内部保持数据的一致性。其中一种实现方式就是使用外键。外键约束是指,假设有一张表格,其中某一列将会包含来自另一张表格列的外键列的值。在 MongoDB 中,不能保证外键将被保留。程序员需要确保数据以这种方式保持一致。虽然未来版本的 MongoDB 可能会实现这一功能,但目前还不存在这样的选择。取而代之的是嵌入式数据的替代方案。


4
只有当父文档拥有嵌入的数据时,嵌入数据才是一种选择。有些情况下,文档具有自己独立的生命周期,但仍需要从其他文档引用。如果我理解正确,在这种情况下就无法保持一致性,导致随着时间推移不可避免地出现数据降级。最糟糕的情况是,人们将尝试寻找解决方案,浪费全球范围内的时间来解决一个根本无法解决的问题。 - Tamas Hegedus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接