我正在构建一个用户有活动提要的社交应用程序。如果用户属于同一组,则提要中的项目将相同。
所以…该应用程序有许多组,用户可以选择属于这些组。如果事件发生,将为该组中的每个用户创建活动提要项。
但是我现在想到了一个有userid数组的单一文档的想法,没有可以针对活动提要项采取的操作,所以我们没有什么可担心的。
我的问题是这两种方法中哪一种是最好的,或者有更好的选择?预计一个群组可以容纳超过1万名用户。检查我的理解:
- 一个用户有多个组,一个组有多个用户(M:N)。
- 1个用户有1个活动源(1:1)
- 1个活动feed有许多事件(1:M)
- 1个事件有多个用户(1:M)
所以,你的集合是:
- 用户
- 组
每个事件的FK为groupId
。每个用户将有一个groupId
s数组。
创建用户活动提要的查询应该是:
Events.find({groupId: {$in: user.groups}});
在groupId上索引,当需要扩展时,你可以保存一个默认的活动feed &把它发给所有没有组(或有默认组)的人。这就是reddit做的。
尽量避免在1:M关系中使用数组。
您没有提到的一个选项是创建类似Memberships
集合的东西,其中文档具有{userId, groupId}
的形式,并在两个字段上创建唯一的复合索引,如
Memberships._ensureIndex({groupId: 1, userId: 1}, {sparse: true, unique: true})
这样创建索引可能是有意义的,因为您将查找特定组中的用户,并将帖子加入到该组id。如果你要按用户查找组,那么你可以先索引userId
。
如果您打算同时为每个用户显示来自多个组的联合的活动,您可能会遇到响应性连接问题,在这种情况下,如果组更改,则在用户刷新页面之前不更新提要可能会更简单。
我建议您创建自己的publish
方法,以便您只订阅相关数据,而不向本地mongo部署太多数据。你可以在这里找到一个Flow-Router和基于路由的订阅的例子:
我认为最有效的选择是将每个活动提要嵌入到每个用户文档中:
{
"firstname" : "Joe",
"lastname" : "Bloggs",
"activities": [{
"title": "Someone did something"
}, {
"title": "Someone did something else"
}]
}
以Facebook为例,我想活动提要上的项目很少改变。但它们会被大量阅读。每次加载activity feed时,执行一个昂贵的连接查询(在非关系NoSQL产品上)将降低性能。
你最好将其嵌入User
本身,因为当你拥有当前用户时,你也将拥有他们的活动提要。
当一个活动被触发&需要添加到1万用户,那么这肯定需要更长的时间。但这可以在后台发生&需要多久就多久。用户看到好友的活动并不重要。
这种方法也有缺点。例如,您可能希望减少活动数组,或者您可能会为单个用户获取大量数据。然后扔掉一大堆。