Mongodb:从每个组中选择前N行

Tac*_*aza 12 mongodb

我在我的博客平台上使用mongodb,用户可以在其中创建自己的博客.所有博客的所有条目都在条目集合中.条目的文档如下所示:

{
  'blog_id':xxx,
  'timestamp':xxx,
  'title':xxx,
  'content':xxx
}
Run Code Online (Sandbox Code Playgroud)

正如问题所说,有没有办法为每个博客选择最后3个条目?

chr*_*dam 17

您需要首先按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]
            }
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

  • 如果每个组有几千个文档,我想小组阶段会将它们全部保存在“docs”数组中,而我们只需要最后 3 个,而不必保留其他任何内容。你知道在 Mongo 4.2 中是否有一种方法可以提高效率(在“docs”中最多保留 3 个文档)?(我想在 4.4 中你可以使用自定义累加器函数。) (3认同)

Rem*_*iet 1

如果你能忍受两件事,那么在基本的 mongo 中做到这一点的唯一方法:

  • 参赛文件中的附加字段,我们称之为“年龄”
  • 新的博客条目进行了额外更新

如果是这样,您可以这样做:

  1. 创建新的介绍后,进行正常插入,然后执行此更新以增加所有帖子的年龄(包括您刚刚为此博客插入的帖子):

    db.entries.update({blog_id: BLOG_ID}, {年龄:{$inc:1}}, false, true)

  2. 查询时,使用以下查询将返回每个博客的最新 3 个条目:

    db.entries.find({age:{$lte:3}, 时间戳:{$gte:STARTOFMONTH, $lt:ENDOFMONTH}}).sort({blog_id:1,age:1})

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