如何处理mongodb中的多对多关系

Posted

技术标签:

【中文标题】如何处理mongodb中的多对多关系【英文标题】:How to handle many to many relationships in mongo 【发布时间】:2020-10-09 21:43:34 【问题描述】:

在猫鼬模式中构建多对多模型的最佳方法是什么?

我有两个模型,它们之间存在多对多关系。用户可以属于多个组织,组织可以有多个用户。

选项:

    通过引用另一个模型来定义每个模型中的关系 通过引用另一个模型来定义一个模型中的关系

选项 1

const UserSchema = new Schema(
  organiations:  type: Schema.Types.ObjectId, ref: "Organiation" , // references organisation
)

mongoose.model("User", UserSchema)

const OrganiationSchema = new Schema(
  users:  type: Schema.Types.ObjectId, ref: "User" , // references users
)

mongoose.model("Organiation", OrganiationSchema)

一开始这似乎是个好主意,这意味着我可以查询组织模型以获取所有用户,也可以查询用户模型以获取所有相关组织。

唯一的问题是我必须维护 2 个事实来源。如果我创建一个组织,我必须用它所属的组织更新用户,并且我必须用它拥有的用户更新组织。

这使我想到了选项 2,即通过仅在一个模型中定义关系来获得一个事实来源。

选项 2:

const UserSchema = new Schema(
  organiations:  type: Schema.Types.ObjectId, ref: "Organiation" , // references organistion
)

mongoose.model("User", UserSchema)

const OrganiationSchema = new Schema() // no referencces

mongoose.model("Organiation", OrganiationSchema)

这意味着当我创建一个新组织时,我只需要将用户更新为他们所属的组织。没有两个来源不同步的风险。但是,这确实意味着在查询数据时,它会变得更加棘手。如果我想获取属于某个组织的所有用户,我必须查询用户文档。这意味着我的组织控制器必须了解用户和组织模型,并且当我开始添加更多关系和模型时,我会在所有这些我想要避免的模块之间获得紧密耦合。

您建议如何在猫鼬模式中处理多对多关系?

【问题讨论】:

您对选项的看法是正确的,不要忘记选项 1 可能会导致大型组织的用户列表中有很多用户。您可以在这两种策略之间做出选择。 您说得对,大型组织可能有很多用户。但这也可能是选项 2 的问题。如果我试图在他们的组织数组中找到所有具有 organization._id 的用户,那么这不是很优雅。不确定猫鼬如何处理这个问题,但可能是一个潜在的性能问题。 如果您真的关心性能,则需要优先考虑要求(查询时间/存储空间/查询灵活性)并将您的架构调整到这些要求。 当您提到拥有大量用户的组织时,我不确定我是否理解您在暗示什么。这如何只影响选项 1 而不会影响选项 2? 如果您有一个拥有 10000 个用户的组织,则每个用户在 organizations 数组中都有一个组织,但该组织在其 users 数组中具有 10000 个用户。用户属于 10000 个组织的可能性较小。 【参考方案1】:

对此没有固定的解决方案。

如果组织拥有的用户数量比用户拥有组织的数量多,那么选项 2 可能是更好的解决方案。

在性能方面,只要引用的 id 被编入索引,填充引用的数据将大致相同。

话虽如此,您可能仍会选择选项 1,即使您的组织收藏有可能拥有“巨大”的数组。特别是如果您想进行简单的计算,例如组织用户的数量或使用“组织的当前用户 ID 到其他集合”。在这种情况下,选项 1 会更好。

但是,如果您选择选项 1,并且您的阵列有可能变得非常大,请考虑存储桶设计模式。基本上,您限制了嵌套数组的最大长度。如果数组达到其最大长度,则创建另一个包含新添加的 id(或嵌套文档)的文档。将其视为分页。

【讨论】:

谢谢,尽量避免大量数据是有意义的。我没有考虑桶设计模式。您的意思类似于mysql如何使用具有每个项目的键/ ID的各种映射表处理多对多关系?在 mongo 的情况下,创建一个引用 user._id 和 organization._id 的新文档? 是的,但比 sql 方式要好得多。不是引用一组 user._id 和 organization._id,而是使用单个 organization._id 存储 user._id 数组。基本上在大多数情况下,您不需要扩展您的原始组织文档。但是,如果由于某种原因组织中的用户数量增长过大(例如 100,000),那么您可以制作一个引用文档,该文档可以在单个扩展文档中存储另外 100,000 个用户 看看这个链接:mongodb.com/blog/post/building-with-patterns-the-bucket-pattern

以上是关于如何处理mongodb中的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

如何处理 JSON 中的多对多关系?

如何处理淘汰视图模型中的多对多关系

MongoDB 多对多关联

使用 Spring Boot、Jackson 和 Hibernate 的多对多关系

了解 MongoDB 中的多对多关系以及如何取消引用集合

MongoDB中的多对多关系