Mongodb:从每个组中选择前N行
我使用mongodb作为我的博客平台,用户可以在这里创建自己的博客。来自所有博客的所有条目都在条目集合中。条目的文档如下所示:Mongodb:从每个组中选择前N行,mongodb,Mongodb,我使用mongodb作为我的博客平台,用户可以在这里创建自己的博客。来自所有博客的所有条目都在条目集合中。条目的文档如下所示: { 'blog_id':xxx, 'timestamp':xxx, 'title':xxx, 'content':xxx } 正如问题所说,是否有任何方法可以为每个博客选择(比如)最后3个条目?可以使用组(聚合),但这将创建一个完整的表扫描 你真的需要3篇吗?或者你能设定一个限制吗…例如:上周/月最多3篇帖子?如果你能接受两件事,那么在基本mongo中
{
'blog_id':xxx,
'timestamp':xxx,
'title':xxx,
'content':xxx
}
正如问题所说,是否有任何方法可以为每个博客选择(比如)最后3个条目?可以使用组(聚合),但这将创建一个完整的表扫描
你真的需要3篇吗?或者你能设定一个限制吗…例如:上周/月最多3篇帖子?如果你能接受两件事,那么在基本mongo中实现这一点的唯一方法是:
- 您的输入文档中还有一个字段,我们称之为“年龄”
- 一个新的博客条目进行了额外的更新
请注意,此解决方案实际上是并发安全的(没有重复期限的条目) 这个答案使用了另一个问题的drcosta的map reduce
您需要首先按照
blog\u 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]
}
}
}
])
理想情况下,我只想选择3篇,但如果我除了数据非规范化之外找不到解决方案,上个月最多3篇文章就足够了。你能给我举个例子说明如何做到这一点吗?从我读过的所有mongodb的map reduce教程中,它们只显示了如何计算统计数据(聚合)…明白你的想法了。我没想到会有这样的事。创建新帖子时进行额外更新不会有问题。但是,当用户删除一篇文章时,我们必须更新所有其他文章的“年龄”字段。只有当被删除的帖子有“年龄”时,更新才能被限制。是的,你不应该将更新限制在年龄<3岁,因为你最终会有重复的年龄。就地更新速度非常快,所以应该不会有问题。删除意味着删除条目并将年龄减少1,其中年龄>已删除\ u post.age。祝你好运,这绝对有道理。谢谢你的建议!它适用于少量记录和罕见的更新,但当我需要从两个用户之间的每次对话中获取最后一条消息时,当我每分钟有数千条消息和许多新消息时,将它与消息传递系统一起使用是否有效?我认为每次更新数千条信息的“年龄”是无效的。您能为这种情况提供一些建议吗?@oyatek有点取决于您的确切用例和读/写比率。如果你打开一个关于你的具体问题的问题,我会看一看。自从聚合变得可用以来,现在这是更好的答案。如果每个组都有数千个文档,我想组阶段会将它们全部保存在
文档
数组中,而我们只需要最后3个,而不必保留任何其他内容。您知道Mongo4.2中是否有更有效的方法(在文档中最多保存3个文档
)吗?(我想在4.4中可以使用自定义累加器函数。)
db.entries.aggregate([
{ '$sort': { 'blog_id': 1, 'timestamp': -1 } },
{
'$group': {
'_id': '$blog_id',
'docs': { '$push': '$$ROOT' },
}
},
{
'$project': {
'top_three': {
'$slice': ['$docs', 3]
}
}
}
])