MongoDB数组或单独的集合

时间:2014-02-24 06:46:08

标签: mongodb

我有一个用户集合。 每个用户可能有:   - 大量粉丝(100K +),可能跟随大量其他用户。   - 大量收藏夹   - 查看的大量项目

我看到2个架构设计。关于查询,我需要找到用户关注的人 我还需要知道收藏夹,观看给定用户的列表。 所有列表(关注者,关注者,收藏者必须具有唯一条目

我试图通过Google找到类似的问题或主题但找不到任何内容。

MongoDB可以像这样处理大型数组吗?或者我应该采用设计方法2,将映射存储在单独的集合中,这使我可以拥有无​​限制的映射数量?

我很感激你的宝贵想法。

我选择2,因为它允许我拥有无限数量的映射。 但在我走这条路之前,我想检查是否会出现我可能不想要的问题。

从一种设计转移到另一种设计将是昂贵的。

Design 1 (EMBEDDED ARRAY TO STORE MAPPINGS):
[
{
  user: bob, //(key)
  followers: ["Alex", "john", "steve", "mark", ... 200K+ entries]
  following: ["Mila", "mark", "Bill", "Joe", ... 100K+ entries]
  favorites: [ObjectI(1), ObjectId(2),...5K+ entries]
  watched: [ObjectI(4), ObjectId(5),...100K+ entries]
},
{
  user: Nick, //(key)
  followers: [bob", "kery", "Jery", "Tom", ... 200K+ entries]
  following: ["Tim", "Shane", "Sally", "Joe", ... 100K+ entries]
  favorites: [ObjectI(4), ObjectId(5),...5K+ entries]
  watched: [ObjectI(2), ObjectId(9),...100K + entries]
}
]

设计2(单独收集商店映射)

user_followers collection:
[
 { user: bob, follower: "Alex" }, //key: (user, follower)
 { user: bob, follower: "john"}, 
 { user: bob, follower: "steve"}, 
 { user: bob, follower: "mark"}
  ... 200K+ entries
]

user_following collection:
[
 { user: bob, following: "Mila"},  //key (user, following)
 { user: bob, following: "mark"},
 { user: bob, following: "Bill"}, 
 { user: bob, following: "Joe"},
 ... 100K+ entries
]

user_favorites collection:
[
 { user: bob, favorite: ObjectId(1)},
 { user: bob, favorite: ObjectId(3)},
 { user: bob, favorite: ObjectId(6)},
 ... 5k entries
},

2 个答案:

答案 0 :(得分:1)

  

MongoDB可以像这样处理大型数组吗?或者我应该采用设计方法2,将映射存储在单独的集合中,这使我可以拥有无​​限制的映射数量?

在MongoDB中,文档可以是at most 16 MB。使用您的第一个设计,您可能会达到我想象的极限。

关于第二个设计,在我看来user_followersuser_following集合只重复相同的数据:如果bob跟随martha,那么bob是martha的追随者,所以你可以合并将这两个集合合并为一个具有{ followed: 'martha', follower: 'bob' }

等条目的集合

<强>更新

评论中有关于如何处理双向关系或查询索引的问题。

鉴于两个用户bob和martha,他们要么没有关系,要么bob跟着martha,或者martha跟着bob,或者bob和martha跟随对方,即三种不同的可能关系。

现在,对于bob跟随martha的情况,关注者集合将是

[
  {
    followed: 'martha',
    follower: 'bob'
  }
]

对于马莎跟随鲍勃的情况,它将是

[
  {
    followed: 'bob',
    follower: 'martha'
  }
]

当两者互相追随时

[
  {
    followed: 'martha',
    follower: 'bob'
  }, {
    followed: 'bob',
    follower: 'martha'
  }
]

此设计中唯一昂贵的操作在设计1和2中也很昂贵,原因相同:我们需要隔离两个集合之间的共同元素;该操作是找到双向关系(例如bob和martha跟随彼此)。

就索引而言,只有两个有任何用处,{ follower: 1, followed: 1 }{ followed: 1, follower: 1 }(两者都只对排序有用,因为这两个中的任何一个都会涵盖所有过滤案例)。

现在回到设计2,上面的使用cas将是:

鲍勃跟随玛莎

user_followers

[
  {
    user: 'martha',
    follower: 'bob'
  }
]

user_following

[
  {
    user: 'bob',
    following: 'martha'
  }
]

玛莎跟随鲍勃

user_followers

[
  {
    user: 'bob',
    follower: 'martha'
  }
]

user_following

[
  {
    user: 'martha',
    following: 'bob'
  }
]

鲍勃和玛莎互相追随

user_followers

[
  {
    user: 'bob',
    follower: 'martha'
  }, {
    user: 'martha',
    follower: 'bob'
  }
]

user_following

[
  {
    user: 'martha',
    following: 'bob'
  }, {
    user: 'bob',
    following: 'martha'
  }
]

现在我们可以看到,正如我所说,设计2会复制所有关注者信息,绝对没有任何好处。

答案 1 :(得分:1)

初看起来我在这里看到设计1很可能会创建对于mongo而言太大的文档,并且16MB的大小限制可能是一个问题。

另外,你有没有想过你的索引?如果你必须在一大堆例如users.following内搜索关系,我认为这对性能来说太糟糕了。我觉得像第二种设计一样明智。有了它,你可以拥有表现非常好的简单索引。

PS:followersfollowing收藏是否真的有原因?也许你可以把它们合二为一。