2011-06-27 70 views
9

我使用mongodb作为我的博客平台,用户可以在其中创建自己的博客。所有博客中的所有条目均位于条目集合中。一个条目的文档如下所示:Mongodb:选择每个组的前N行

{ 
    'blog_id':xxx, 
    'timestamp':xxx, 
    'title':xxx, 
    'content':xxx 
} 

正如问题所述,是否有任何方法可以为每个博客选择最后3个条目?

回答

1

做到这一点基本蒙戈如果你可以用两件事情唯一可行的生活方式:

  • 您的输入文档中的另外一个领域,我们称之为“年龄”
  • 一个新的博客条目服用其他更新

如果是这样,这里是你如何做到这一点:

  1. 在创建一个NE w介绍是否正常插入,然后执行此更新以增加所有帖子的时间(包括刚刚为此博客插入的帖子):

    db.entries.update({blog_id:BLOG_ID},{age:{ $ INC:1}},假,真)

  2. 查询时,请使用以下查询将返回最近的3项为每个博客:

    db.entries.find({年龄:{$ LTE:3},时间戳:{$ GTE:STARTOFMONTH,$ LT:ENDOFMONTH}})排序({blog_id:1,年龄:1})

请注意,此解决方案实际上是并发安全的(没有重复年龄的条目)。

+0

有你的想法。我没有想到这样的事情。创建新帖子时的额外更新不会成为问题。但是,当用户删除帖子时,我们必须更新所有其他帖子的“年龄”字段。只有删除的帖子“年龄”<= 3时,该更新才能被限制。我错过了什么? – Tacaza

+0

是的,您不应该将更新限制为年龄<3,因为您最终会得到重复的年龄。就地更新非常快,所以它不应该是一个问题。删除意味着删除条目并将年龄减少1,其中age> deleted_post.age。祝你好运。 –

+0

这绝对有道理。感谢您的建议! – Tacaza

0

它可能与组(聚合),但这将创建一个全表扫描。

你确实需要3个或者你能设置一个限制吗......例如:最多3个帖子/上个星期/月?

+0

理想我想精确地选择3,但是从上个月最多3个职位可够好,如果我不能找到除了数据非规范化的解决方案。你能举个例子说明如何做到这一点吗?从所有mongodb的地图缩小教程我已阅读他们只显示如何计算统计(聚合)... – Tacaza

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}); 
8

您需要首先由blog_idtimestamp场集合中的文档进行排序,然后做一个初步按降序创建原始文档的数组。之后,您可以使用文档切片数组以返回前3个元素。

直觉可以遵循下面的例子:

db.entries.aggregate([ 
    { '$sort': { 'blog_id': 1, 'timestamp': -1 } }, 
    {  
     '$group': { 
      '_id': '$blog_id', 
      'docs': { '$push': '$$ROOT' }, 
     } 
    }, 
    { 
     '$project': { 
      'top_three': { 
       '$slice': ['$docs', 3] 
      } 
     } 
    } 
]) 
+0

谢谢,辉煌 –