Min*_*ark 5 optimization mongodb
我是mongodb的新手,也许这是一个微不足道的问题.我有两个mongodb集合:user
和post
.用户可以创建和关注多个帖子,并按照上次修改日期列出帖子.特定帖子后可能会有大量用户,因此我不想在每个帖子文档中保留关注者列表.另一方面,一个用户可能不会关注超过几千个帖子,因此我决定在每个用户文档中保留关注帖子的对象列表.
为了能够快速列出给定用户的50个最近修改的帖子,我选择保留该last_updated_at
字段以及post objectid.
该post
文件相当基础:
{
"_id" : ObjectId("5163deebe4d809d55d27e847"),
"title" : "All about music"
"comments": [...]
...
}
Run Code Online (Sandbox Code Playgroud)
该user
文件如下:
{
"_id": ObjectId("5163deebe4d809d55d27e846"),
"posts": [{
"post": ObjectId("5163deebe4d809d55d27e847"),
"last_updated_at": ISODate("2013-04-09T11:27:07.184Z")
}, {
"post": ObjectId("5163deebe4d809d55d27e847"),
"last_updated_at": ISODate("2013-04-09T11:27:07.187Z")
}]
...
}
Run Code Online (Sandbox Code Playgroud)
当用户创建或关注帖子时,我可以简单地在用户文档中$push
的帖子ObjectId
和列表last_updated_at
的末尾posts
.修改帖子时(例如,当评论添加到帖子中时),我会last_updated_at
在所有关注者的用户文档中更新该帖子的字段.那很重,但我不知道如何避免它.
当我想获得用户的50个最近更新的帖子列表时,我很遗憾地需要获得所有后续帖子的列表,然后last_updated_at
在内存中排序,然后仅保留前50个帖子.
所以当我修改帖子时,我尝试更改实现以重新排序列表:我$push
到列表的末尾,$pull
它来自任何地方.由于这是一个两步程序,因此存在竞争条件,我可能会在列表中获得两倍相同的帖子.有没有更好的方法来维护mongodb中的排序数组?
由于您可能经常更新给定用户的最新帖子,因此您可能希望避免不必要地重写数据以维护已排序数组的开销.
更好的方法是将数据模型展平并使用单独的集合而不是有序数组:
(userID, postID, lastUpdated)
update()
使用multi:true
和upsert:true
选项以及$set
last_updated_at对新值执行简单操作.find()
使用排序和限制选项执行常规操作.如果你想维护有序数组,MongoDB 2.4增加了两个与这个用例相关的有用功能:
因此,您可以实现推送到按上次更新日期降序排序的50个项目的固定大小数组的结果:
db.user.update(
// Criteria
{ _id: ObjectId("5163deebe4d809d55d27e846") },
// Update
{ $push: {
posts: {
// Push one or more updates onto the posts array
$each: [
{
"post": ObjectId("5163deebe4d809d55d27e847"),
"last_updated_at": ISODate()
}
],
// Slice to max of 50 items
$slice:-50,
// Sorted by last_updated_at desc
$sort: {'last_updated_at': -1}
}
}}
)
Run Code Online (Sandbox Code Playgroud)
在$push
将更新排序的顺序列表,以及$slice
列表修剪的前50项.由于帖子不是唯一的,您仍然需要$pull
先从列表中找到原始文件,例如:
db.user.update(
// Criteria
{ _id: ObjectId("5163deebe4d809d55d27e846") },
// Update
{
$pull: {
posts: { post: ObjectId("5163deebe4d809d55d27e847") }
}
}
)
Run Code Online (Sandbox Code Playgroud)
这种方法的一个好处是数组操作正在服务器上完成,但与在应用程序中对数组进行排序一样,您可能仍然需要更新文档.