我正在开发一个与 10Gen Socialite Project 非常相似的社交活动供稿系统,该系统已经在生产中运行了几年。我有一个新用例,其中我需要存储按时间顺序排列的每个用户的活动列表,其中活动列表应该:
- 只包含最近插入的 N 项
- 不插入语义等效项的重复项
- 允许对结果进行分页。
到目前为止,我已经提出了两种解决此问题的方法,但两者似乎都有令人不安的局限性。
第一种方法(与我的其他集合非常匹配)是有一个集合,其中包含每个活动的一个文档,由用户 ID 索引。例如:
{
"owner": {
"type": "user",
"id" : "1234"
},
"activity": {
"published": "2013-09-27T17:08:26+00:00",
"actor": {
"type": "elastic-search-node",
"id": "2"
},
"verb": "recommend",
"object": {
"type": "review",
"id": "1093773"
}
"uuid": "6d70eaa4-0766-4949-971d-98740cb9eca1"
}
}
每次我收到给定用户的新活动时,我都会插入一个如上所述的文档,其中包含相同的“所有者”子句但不同的“活动”子句。但是,我不确定处理插入的最有效方法。鉴于上述标准,一种伪代码方法将是:
results = collection.update(
{
'owner.id':'1234',
'activity.verb':'recommend',
'activity.object.type':'review',
'activity.object.id':'1093773'
},
the_activity,
upsert:true)
# count documents for owner.id = 1234
# if count > max_documents, delete oldest document
这种方法的问题是它可能需要多达 3 次数据库操作才能完成插入和修剪。但是,使用“upsert”可以防止重复,我们可以使用生成的 ObjectID 进行时间查询和分页。
我研究过的另一种方法类似于 Socialite 中的FanoutOnWriteSizedBuckets方法。在这种情况下,活动列表作为子文档存储在 max-size 数组中,由用户 ID 索引。例如:
{
"owner" : {"type":"user", "id":"1234"},
"feed" : [
{"_id" : ObjectId("...da7"), "activity" : ...},
{"_id" : ObjectId("...dc1"), "activity" : ...},
{"_id" : ObjectId("...dd2"), "activity" : ...}
]
}
在这种情况下,查询也相当简单,但同样,插入是有问题的。我已经研究过使用 $update、$push、$addToSet、$ne、$each 等的各种技术和组合,但似乎没有一个能够以更有效的方式实现防止重复插入和修剪操作以上。
任何人都可以提出解决此用例的方法吗?
谢谢!
(x-发布到 mongodb-user Google Group) 已 解决: https ://groups.google.com/forum/#!topic/mongodb-user/ K8n7Gf1nv3Q