MongoDB与大规模的多对多关系

时间:2015-08-08 01:32:30

标签: mongodb

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

MongoDB Many-to-Many Association

How to organise a many to many relationship in MongoDB

我可以通过这种设置看到的问题是MongoDB的16MB文档限制。假设我有user s,grouppost s。 post有一个关联的group和许多user可以喜欢它。 group中有postuser个,其中有许多user可以跟随它。 post可以有很多人喜欢group,并且可以关注多个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 。如果我用关系数据库构建它,我会这样设置:

group

理论上,post可以有userpostuseruserpost可以拥有无​​限数量的group <div class="parent"> <div class="child">...</div> <div class="child">...</div> ... </div> 如果在SQL查询中正确完成分页,则 .parent{ margin-right: -2%; /* to compensate for the unwanted margin of what ends up being the right-most element */ } .child{ display: inline-block; width: 23% /* I want 4 columns, so it'll be a little less than 25%, right? */ margin-right: 2% /* So width + margin-right percent add up to 25% */ margin-bottom: ? /* Can't say 2% because it's NOT 2% of the parent container's width */ height: 100px; /* constant value */ } 可以拥有无​​限数量的受欢迎write.csv(cats, "cats_with_numbers.csv", row.names=FALSE) std::string type; TYPE get_type(std::string) { ... } get_type(type) new_variable(); s。

如何设置MongoDB的架构以便实现这种扩展?

2 个答案:

答案 0 :(得分:9)

这是一个很好的问题,它说明了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"
}

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

db.post_likes.find(
  {"postId":someValue},
  {_id:0,user_name:1}
)

只存储了ID,这个相当常见的任务至少需要两个查询,并且 - 考虑到约束,可能会有无数个类似的帖子 - 可能巨大内存消耗(你需要将用户ID存储在RAM中。

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

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

db.post_likes.update(
  {"post_id":someId},
  { $set:{ "post_title":newTitle} },
  { multi: true}
)

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

底线

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

答案 1 :(得分:0)

如果您只是在覆盖集合数组中存储关系的ID,那么在单个文档中不应该有太多问题。可以使用GridFS,但这通常更适用于文件,音乐,视频等媒体,使用GridFS会使更新变得痛苦