与MongoDB有很多很多关系

Mik*_*e V 8 mongodb

我已经看过很多关于如何与MongoDB建立多对多关系的帖子,但没有一个提到规模.例如这些帖子:

MongoDB多对多关联

如何在MongoDB中组织多对多的关系

我可以通过这种设置看到的问题是MongoDB的16MB文档限制.说我有users,groups和posts.posts有一个相关的group和许多user可以喜欢它的s.A中group有很多posts,很多user都可以遵循它.A user可以有许多喜欢post的,可以跟随很多groups.如果我用关系数据库构建它,我会这样设置:

user:
    user_id
    username

post:
    post_id
    group_id
    message

group:
    group_id
    name

post_likes:
    post_id
    liked_user_id

group_followers:
    group_id
    follower_user_id
Run Code Online (Sandbox Code Playgroud)

从理论上讲,a group可以有一个极小数量的posts和users,a post可以拥有无​​限数量的喜欢users,并且如果在SQL查询中正确完成分页,则user可以拥有无​​限数量的喜欢posts和groups .

如何设置MongoDB的模式以便实现这种规模?

Mar*_*erg 10

这是一个很好的问题,它说明了overemebedding的问题以及如何处理它.

示例:发布喜欢

让我们坚持用户喜欢帖子的例子,这是一个简单的例子.其他关系必须相应处理.

你绝对正确的是,将这些内容存储在帖子中迟早会导致非常受欢迎的帖子达到大小限制的问题.

所以你正确地回过头来创建一个post_likes集合.为什么我这称呼为正确?因为它适合您的使用案例和功能和非功能要求!

  • 它无限缩放(嗯,有一个理论上的限制,但它是巨大的)
  • 它很容易维护(创建一个唯一的索引post_idliked_user_id)和使用(用户和帖子都是已知的,所以添加like是一个简单的插入或更可能是一个upsert)
  • 您可以轻松找出哪些用户喜欢哪些帖子以及哪些用户喜欢哪些帖子

但是,我会稍微扩展集合以防止对频繁使用的某些用例进行不必要的查询.

我们现在假设帖子标题和用户名不能改变.在这种情况下,以下数据模型可能更有意义

{
  _id: new ObjectId(),
  "post_id": someValue,
  "post_title": "Cool thing",
  "liked_user_id": someUserId,
  "user_name": "JoeCool"
}
Run Code Online (Sandbox Code Playgroud)

现在让我们假设您要显示喜欢帖子的所有用户的用户名.使用上面的模型,这将是一个相当快速的查询:

db.post_likes.find(
  {"postId":someValue},
  {_id:0,user_name:1}
)
Run Code Online (Sandbox Code Playgroud)

由于只存储了ID,这个相当常见的任务至少需要两个查询,并且 - 鉴于约束条件可能会有一个无限数量的匹配器 - 可能是巨大的内存消耗(您需要将用户ID存储在RAM中) ).

当然,这会导致一些冗余,但即使数百万人喜欢帖子,我们只谈论几兆字节的相对便宜(且易于扩展)的磁盘空间,同时在用户体验方面获得了很多性能.

现在有了这样的事情:即使用户名和帖子标题可能会发生变化,您只需进行多次更新:

db.post_likes.update(
  {"post_id":someId},
  { $set:{ "post_title":newTitle} },
  { multi: true}
)
Run Code Online (Sandbox Code Playgroud)

您正在进行交易,需要一段时间才能做一些非常罕见的事情,比如更改用户名或帖子,以便极其频繁地发生用例.

底线

请记住,MongoDB是面向文档的数据库.因此,请记录您感兴趣的事件,并使用未来查询所需的值并相应地对数据建模.