在 MongoDB 中设计多对多关系(而不是关系表)

Designing Many-to-Many relationships in MongoDB (instead of relational tables)

用一个经典的例子——假设我们有一个应用程序,它有一个课程集合和一个学生集合,而每个学生可以参加很多课程,每个课程可以有很多参与者。

我们需要查询一个学生参加的所有课程,但是我们也需要查询参加单个课程的学生。

我知道使用关系型数据库来处理这个问题是最优的解决方案,但是目前我只想使用一种类型的数据库MongoDB,现在我想问一下这种模式设计是否可以工作效率?使用它的利弊是什么?哪个设计可以更好?

User: {
   _id,
   //...properties
}

Course: {
   _id,
   //...properties
}

CourseParticipate: {
   _id,
   userId,
   courseId,
   //...properties
}

CourseAdmin: {
   _id,
   userId,
   courseId,
   //...properties
}

现在我喜欢这个设计是因为将来如果我有能力处理多个数据库,很容易将这些集合转移到关系数据库(或者不是?),我也喜欢它因为它是快速写入数据并删除对象之间的关系,但如我所见,它会使读取查询变慢一点(或很多?)。

因为之前在网上没见过这种设计,所以我已经知道有更好的解决方案(希望不要因为我是新人而听到中肯的评论和回答)。

我也想听听您的意见 Neo4j 是否可以处理这个问题?什么关系数据库在 MongoDB 旁边效果最好?

文档和文章的链接将非常有帮助! 谢谢!

这是一个具有多对多关系的数据的情况。我认为你的数据库中有几千名学生和几百门课程。

首先,我可以使用以下设计,将每个学生嵌入的课程详细信息作为称为 courses.

的子文档数组
- students collection
id:
name:
courses: [ { id: 1, name: },  { id: 5, name: }, ... ]

- courses collection
id:
name:
description:

请注意,课程 ID 和名称存储在两个集合中。这是数据的重复。这应该没问题,因为重复的详细信息不会经常更改(或者可能根本不会更改)。

查询某学生报读的所有课程,例如:db.students.find( { name: "John" } )。这将 return 一份具有匹配名称和所有课程(数组字段)的学生文档。参见 db.collection.find

查询注册特定课程的所有学生:db.students.find( { "courses.name": "Java Programming" } )。这将 return 所有课程名称符合条件“java 编程”的学生文档。参见 Query an Array of Embedded Documents

此外,您可以使用 projection 从结果中排除和 include 字段。

备注:

  • 您可以将学生信息嵌入到课程集合中,而不是将课程嵌入到学生中。查询将与上述类似,但您将查询课程集合。这取决于您的用例。
  • 您可以只将课程 ID 字段存储在学生集合的课程数组中;这是您经常更改课程名称字段的情况。查询将使用聚合 $lookup(“加入”操作)从课程集合中获取课程。
  • 关于 Data Model Design 的基于文档的 MongoDB 数据的信息。