MongoDb 聚合组和排序应用程序

xyz*_*xyz 2 mongodb aggregation-framework

有结构的文档:

{"appId":<id>,"time":<number>}
Run Code Online (Sandbox Code Playgroud)

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

{"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}
Run Code Online (Sandbox Code Playgroud)

是否可以按 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}
Run Code Online (Sandbox Code Playgroud)

我尝试了这个查询:

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

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

mic*_*ckl 5

您可以尝试以下聚合:

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

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