我在我的博客平台上使用mongodb,用户可以在其中创建自己的博客。所有博客的所有条目都在条目集合中。条目的文档如下:
{
'blog_id':xxx,
'timestamp':xxx,
'title':xxx,
'content':xxx
}
正如问题所说,有没有办法为每个博客选择最后3个条目?
答案 0 :(得分:12)
您需要先按blog_id
和timestamp
字段对集合中的文档进行排序,然后执行一个初始组,该组按降序创建原始文档的数组。之后,您可以使用文档切割数组以返回前3个元素。
在这个例子中可以遵循直觉:
db.entries.aggregate([
{ '$sort': { 'blog_id': 1, 'timestamp': -1 } },
{
'$group': {
'_id': '$blog_id',
'docs': { '$push': '$$ROOT' },
}
},
{
'$project': {
'top_three': {
'$slice': ['$docs', 3]
}
}
}
])
答案 1 :(得分:2)
如果你可以忍受两件事,那么在基本的mongo中这样做的唯一方法是:
如果是这样,你就是这样做的:
创建新的介绍后,执行正常插入,然后执行此更新以增加所有帖子的年龄(包括您刚刚为此博客插入的帖子):
db.entries.update({blog_id:BLOG_ID},{age:{$ inc:1}},false,true)
查询时,请使用以下查询,该查询将返回每个博客的最新3个条目:
db.entries.find({age:{$ lte:3},timestamp:{$ gte:STARTOFMONTH,$ lt:ENDOFMONTH}})。sort({blog_id:1,age:1})
请注意,此解决方案实际上是并发安全的(没有重复年龄的条目)。
答案 2 :(得分:1)
这个答案使用地图减少drcosta从另一个问题做了诀窍
In mongo, how do I use map reduce to get a group by ordered by most recent
mapper = function () {
emit(this.category, {top:[this.score]});
}
reducer = function (key, values) {
var scores = [];
values.forEach(
function (obj) {
obj.top.forEach(
function (score) {
scores[scores.length] = score;
});
});
scores.sort();
scores.reverse();
return {top:scores.slice(0, 3)};
}
function find_top_scores(categories) {
var query = [];
db.top_foos.find({_id:{$in:categories}}).forEach(
function (topscores) {
query[query.length] = {
category:topscores._id,
score:{$in:topscores.value.top}
};
});
return db.foo.find({$or:query});
答案 3 :(得分:0)
可以使用组(聚合),但这将创建一个全表扫描。
你真的需要3或者你能设定一个限制吗...例如:上周/月最多3个帖子?