用 MongoDB 中的属性表示多对多关系的最佳模型

2021-12-22 00:00:00 mongodb nosql javascript mysql meteor

表示具有属性的多对多关系的最mongo"方式是什么?

What's the most 'mongo' way of representing many-to-many relationships that have attributes?

例如:

MYSQL 表

people => firstName, lastName, ...

电影 => 名称,长度..

peopleMovies => movieId、personId、语言、角色

将人们嵌入电影...?

Embed people into movies...?

在 MongoDB 中,我知道 非规范化和嵌入 很好,但我不想将人嵌入 电影,这在逻辑上没有任何意义.因为人们不一定只属于电影.

In MongoDB I understand it's good to denormalize and embed but I don't want to embed people into movies, it just doesn't logically make any sense. Because people don't necessarily only have to belongs to movies.

PeopleMovies 将是两个独立的集合.People => embed [{movieId: 12, personId: 1, language: "English", role: "Main"} ...]

People and Movies will be two separate collections. People => embed [{movieId: 12, personId: 1, language: "English", role: "Main"} ...]

Movies => 嵌入 [{movieId: 12, personId: 1, language: "English", role: "Main"} ...]

这个解决方案的问题是,当我们想要更新一个人的 role 用于特定的 movie 时,我们需要运行两个更新查询以确保数据在在两个集合中同步.

The issue with this solution is that when we want to update a person's role for a specific movie we'll need to run two update queries to ensure data is in sync in both collections.

我们也可以做一些更相关的事情,比如最终得到三个集合

We can also do something much more relational like and end up with three collections

People => firstName, lastName, ...电影 => 名称,长度..演员表 => movieId、personId、语言、角色

People => firstName, lastName, ... Movies => name, length .. Castings => movieId, personId, language, role

问题在于,由于 MongoDB 中缺少 join 语句,需要 3 次查询从人 -> 电影,反之亦然.

The issue with this is that because of the lack of a join statement in MongoDB, it would take 3 queries to go from people -> movies and vice versa.

这是我的问题,还有什么其他方法可以在 MongoDB 和更多的 NoSQL 方式中建模这样的东西.就所提供的解决方案而言,哪一个在 mongo 的性能和约定方面是最好的.

Here is my question, what are some other ways to model something like this in MongoDB and in a more NoSQL way. In terms of the solutions provided, which one would be the best in terms of performance and convention in mongo.

推荐答案

在很多方面,meteor 的 API 鼓励扁平化的关系文档,但是 MongoDB 是一个非关系型数据存储.不幸的是,这个冲突留给开发人员解决.

In many ways meteor's API encourages flat relational documents, however MongoDB is a non-relational data store. This conflict is, unfortunately, left as an exercise for the developer to solve.

模式结构和连接的概念是一个庞大的主题,需要在一个答案中涵盖,因此我将尝试尽可能简洁.

The notion of schema structure and joins is an enormous topic to cover within a single answer, so I will attempt to be as succinct as possible.

假设您有评论和发布数据.考虑一下如果您在帖子中嵌入评论会发生什么.

Assume you have comment and post data. Consider what would happen if you embedded comments within your posts.

  • DDP 对文档进行操作.每次在同一帖子中添加新评论时,都会发送所有评论.

  • DDP operates on documents. All of the comments will be sent every time a new comment in the same post is added.

allowdeny 规则对文档进行操作.期望相同的规则同时适用于帖子和评论可能是不合理的.

allow and deny rules operate on documents. It may be unreasonable to expect that the same rules apply simultaneously to both posts and comments.

出版物在收藏方面往往更有意义.在上述场景中,我们无法轻松发布独立于帖子的评论列表.

Publications tend to make more sense in terms of collections. In the above scenario, we could not easily publish a list of comments independent of their posts.

关系数据库的存在是有充分理由的.其中之一是避免第二个解决方案中固有的多次修改问题.

Relational databases exist for good reasons. One of them is to avoid the multiple modification problem inherent in your second solution.

  • MongoDB 本身不支持联接,并且没有产生反应性联接的核心包.

使用您的第三个解决方案.根据我的经验,选择关系模型的原因远远超过数据存储施加的限制.当然,克服缺少连接的问题并不容易,但痛苦可能仅限于少数发布功能.以下是我强烈推荐的一些资源:

Use your third solution. In my experience, the reasons for choosing a relational model far outweigh the restrictions imposed by the data store. Of course overcoming the lack of joins isn't easy, but the pain is likely to be isolated to only a handful of publish functions. Here are some resources I'd highly recommend:

  • 如何发布EventedMind 上的多对多关系.Chris 详细介绍了您的具体用例,但他手动执行了观察回调的反应性连接,我不推荐这样做.

  • How to publish a many-to-many relationship on EventedMind. Chris covers your exact use case in detail, however he manually does the reactive join with observe callbacks, which I don't recommend.

反应式加入流星来自发现流星百科全书.这涵盖了如何以及为什么应该进行反应式连接的基础知识.

Reactive joins in meteor from the Discover Meteor Encyclopedia. This covers the basics of how and why one should do a reactive join.

Discover Meteor 中的非规范化章节.这涵盖了我上面提出的许多观点,还讨论了何时以及如何对某些数据进行非规范化.

The denormalization chapter from Discover Meteor. This covers many of the points I made above and also talks about when and how to denormalize some of your data.

您可以使用发布关系来加入您的数据.替代软件包包括:智能发布、发布复合 和 简单发布.

You can use Publish with relations to join your data. Alternative packages include: smart publish, publish composite, and simple publish.

如果您需要更多信息,请在下方评论,我会更新我的答案.

If you need more information beyond this, please comment below and I will update my answer.

相关文章