对于N:M关系,MongoDB中级联删除的推荐等价物是什么?

问题描述 投票:21回答:2

假设以下“模式/关系”设计,使用级联删除操作删除处理删除的推荐做法是什么?

关系模式:

  +---------+                                    +--------+
  | Student |-*--------1-[Enrollment]-1--------*-| Course |
  +---------+                                    +--------+

MongoDB的:

  +---------+                    +--------+
  | Student |-*----------------*-| Course |
  +---------+                    +--------+

考虑到学生注册课程的经典设计,在使用MongoDB时,学生的课程集合(反之亦然)似乎是一个合适的数据模型(这对于关系/注册表来说没什么用)。但是来自关系世界我应该如何处理删除课程的语义?也就是说,当删除课程时,也应删除所有“注册”记录。也就是说,我应该从每个学生记录的集合中删除该课程。看起来我必须触发2个查询:一个用于删除课程,然后从每个学生的集合中删除它。有没有办法让单个查询执行这种“级联删除”,如语义而无需额外的查询?数据模型是否需要更改?

注意:对于所有其他用例,上述数据模型工作正常:

  • 删除学生=>只是删除该学生以及随之删除的相关课程集合。
  • 学生愿意放弃课程=>只是从学生课程中删除它
  • 添加学生/课程=>只是将其添加到相应的“表格”中。

唯一棘手的事情是处理删除课程。我应该如何处理MongoDB中的这种情况,因为我来自关系背景,我无法弄清楚这一点。

mongodb database-design cascading-deletes non-relational-database database
2个回答
11
投票

你正在做的是在Mongo中做到这一点的最佳和最佳方式。我处于类似的情况,在完成N:M设计模式的所有可能实现后,也达到了同样的解决方案。

显然,这不是一个mongodb的事情,而是更多的NoSQL概念,其中,变化较少的数据(课程)可以单独保存。并且由于删除课程不会是一个非常频繁的操作,它的可行性足以通过所有记录来删除它。

另一方面,你可以让它成为现实。在您的应用程序逻辑中,只需忽略Student文档中课程文档中根本没有reference_id的课程值。但在这种情况下,您必须确保旧的已删除的Course_id不会被重用。

或者只使用课程文档中的已删除标志,并处理应用程序逻辑中的所有其他内容。


3
投票

我将根据Mongo团队的建议回答。我也来自关系数据库,我在开始时理解这些概念时遇到了一些问题。 Mongo团队建议使用“应用程序驱动”模式进行设计,因此您必须首先弄清楚哪些数据组合在一起。请记住,在Mongo中没有任何可能的交易概念,即使我们发明了一个处理交易的驱动程序,我们也应该为此实现自己的解决方案。这意味着如果我有两个业务对象需要同时更新,并且我不能容忍此操作中的失败,我必须将它们加入到单个文档(原子)中。

在您的情况下,您有两个文件,学生和课程,以及当时之间的关系(学生注册N门课程)。我认为课程不需要一直改变,因此它们可以存储在不同的集合中。但重点是它们之间的关系,在这种情况下,你需要自动删除学生和他注册的所有课程。所以最合适的解决方案是将关系嵌入学生,并保持一个单独的课程集合。删除学生时,会同时删除该关系:

学生杰森:

{ _id: ObjectId('...'), name:"John", lastname:"Smith", 
courses: [ 1, 100, 50, 67 ], ...
}

课程可以是它们之间的分离集合。这是在Mongo中处理它的方法。必须将原子操作嵌入到单个文档中。我假设课程是一个不会改变太多的课程列表,如果它们是由学生设计的,我们可以改变一点解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.