首页 > 解决方案 > MongoDb 聚合分组和排序应用程序

问题描述

有结构的文件:

{"appId":<id>,"time":<number>}

对于这个例子,我们假设我们有:

{"appId":"A","time":1}
{"appId":"A","time":3}
{"appId":"A","time":5}
{"appId":"B","time":1}
{"appId":"B","time":2}
{"appId":"B","time":4}
{"appId":"B","time":6}

是否可以按 appId 对文档进行分组,每个组按时间排序,以及从该组的最新时间显示的所有结果,例如:

{"appId":"B","time":6}
{"appId":"B","time":4}
{"appId":"B","time":2}
{"appId":"B","time":1}

{"appId":"A","time":5}
{"appId":"A","time":3}
{"appId":"A","time":1}

我试过这个查询:

collection.aggregate([{"$group":{"_id":{"a":"$appId"},"ttt":{"$max":"$time"}}},
{"$sort":{"_id.ttt":-1,"time":-1}}])

但我只收到了最后一次特定的 appId -> 2 结果,这个查询改变了数据的结构。我想保留文档的结构,并且只像示例一样对它们进行分组和排序。

标签: mongodbaggregation-framework

解决方案


您可以尝试以下聚合:

db.collection.aggregate([
    {
        $sort: { time: -1 }
    },
    {
        $group: {
            _id: "$appId",
            max: { $max: "$time" },
            items: { $push: "$$ROOT" }
        }
    },
    {
        $sort: { max: -1 }
    },
    {
        $unwind: "$items"
    },
    {
        $replaceRoot: {
            newRoot: "$items"
        }
    }
])

您可以在分组之前$sort以获得每个组内的正确顺序。然后,您可以在分组时使用特殊变量$$ROOT来捕获整个 orinal 对象。在下一步中,您可以按$max值排序并使用$unwind$replaceRoot来取回相同数量的文档并将原始形状提升到根级别。


推荐阅读