【问题标题】:Designing Many-to-Many relationships in MongoDB (instead of relational tables)在 MongoDB 中设计多对多关系(而不是关系表)
【发布时间】:2021-05-15 01:11:57
【问题描述】:

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

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

我知道使用关系数据库来处理这将是最佳解决方案,但是现在我只想使用一种类型的数据库,即 MongoDB,现在我想问这种架构设计是否可以有效地工作?使用它的优缺点是什么?哪种设计会更好?

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

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

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

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

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

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

我也想听听 Neo4j 是否可以处理这个问题?以及哪些关系数据库在 MongoDB 旁边效果最好?

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

【问题讨论】:

    标签: database mongodb database-design relational-database


    【解决方案1】:

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

    首先,我可以使用以下设计,每个学生都嵌入课程详细信息,作为称为 courses 的子文档数组。

    - students collection
    id:
    name:
    courses: [ { id: 1, name: },  { id: 5, name: }, ... ]
    
    - courses collection
    id:
    name:
    description:
    

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

    查询学生注册的所有课程,例如:db.students.find( { name: "John" } )。这将返回一个具有匹配名称的学生文档和所有课程(数组字段)。见db.collection.find

    查询注册到特定课程的所有学生:db.students.find( { "courses.name": "Java Programming" } )。这将返回课程名称与标准“java Programming”匹配的所有学生文档。见Query an Array of Embedded Documents

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

    注意事项:

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

    【讨论】:

    • 谢谢!这实际上是我当前的架构设计(将课程 ID 存储在每个用户文档中,并将用户 ID 存储在每个课程文档中),但是我上面建议的架构设计呢?请记住,在这种关系中可能要存储其他信息(例如成绩......),并且有效地修改有关 2 个对象之间关系的信息非常重要。
    • (1)“这实际上是我当前的架构设计(将课程ID存储在每个用户文档中,并将用户ID存储在每个课程文档中)”。它与我所描述的相同。 (2) “请记住,在这种关系中可能要存储其他信息(例如成绩...),..”。当然,您可以在学生收藏中包含成绩。 MongoDB 具有灵活的模式,您可以在稍后包含成绩信息,而无需重新创建表结构。 (3) 为什么要将数据库从最初的 MongoDB 更改为关系数据库 - 后来?
    • (1) 是的,抱歉,您认为将课程 ID 仅存储在学生文档中作为数组会使得查找所有参加课程的学生的查询高效吗? (我正在阅读您附加的“查询嵌入式文档数组”文档,如果答案写在文档中,则无需回答我)。 (3)我在网上某处看到这个问题的最佳解决方案是使用关系数据库,但现在我从你那里了解到,没有必要这样做。
    • “您认为将课程 ID 仅存储在学生文档中作为数组会使得查找所有参加课程的学生的查询高效吗?”。这将是有效的。您可以在数组字段上定义索引(这样您的查询可以快速高效)——这些被称为多键索引。有关详细信息,请参阅Indexes
    猜你喜欢
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 2013-01-02
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多