我有一个用户集合。 每个用户可能有: - 大量粉丝(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
},
答案 0 :(得分:1)
MongoDB可以像这样处理大型数组吗?或者我应该采用设计方法2,将映射存储在单独的集合中,这使我可以拥有无限制的映射数量?
在MongoDB中,文档可以是at most 16 MB。使用您的第一个设计,您可能会达到我想象的极限。
关于第二个设计,在我看来user_followers
和user_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:followers
和following
收藏是否真的有原因?也许你可以把它们合二为一。