mongodb - 如何使用group by进行聚合并正确排序

标签 mongodb aggregation-framework

我正在使用 Mongodb。 考虑我的下一个文档:

{ uid: 1, created: ISODate("2014-05-02..."), another_col : "x" },
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 1, created: ISODate("2014-05-01..."), another_col : "f" },
{ uid: 2, created: ISODate("2014-05-22..."), another_col : "a" }

我想做的是对 uid 进行简单的分组,并按降序对创建的内容进行排序,这样我就可以获得每个 uid 的第一行。

预期输出的示例

{ uid: 1, created: ISODate("2014-05-05..."), another_col: "y" },
{ uid: 2, created: ISODate("2014-05-22..."), another_col: "a" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col: "w" }

我能得到的最好的是:

db.mycollection.aggregate( {$group: {_id: "$uid", rows: {$push: { "created" : "$created" }}}}, sort { // doesnt work well }  )

任何人都可以指导我正确组合分组依据和排序吗? 它只是没有像我预期的那样工作。 (注意:我已经检查了很多线程,但我无法找到适合我的情况的正确答案)

最佳答案

这里有一些需要理解的地方。

当您使用$group时边界将按照发现的顺序排序,没有初始阶段或结束阶段 $sort手术。因此,如果您的文档最初的顺序如下:

{ uid: 1, created: ISODate("2014-05-02..."), another_col : "x" },
{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },

然后只需使用 $group没有 $sort管道的最后会返回如下结果:

{ uid: 1, created: ISODate("2014-05-05..."), another_col : "y" },
{ uid: 3, created: ISODate("2014-05-05..."), another_col : "w" },
{ uid: 2, created: ISODate("2014-05-10..."), another_col : "z" },

这是一个概念,但实际上您所期望的结果似乎需要按 uid 的排序顺序返回“最后其他字段”,这就是您正在寻找的内容。在这种情况下,获取结果的方法实际上是首先 $sort 然后使用 $last运算符:

db.mycollection.aggregate([

    // Sorts everything first by _id and created
    { "$sort": { "_id": 1, "created": 1 } },

    // Group with the $last results from each boundary
    { "$group": {
        "_id": "$uid",
        "created": { "$last": "$created" },
        "another_col": { "$last": "$created" }
    }}
])

或者基本上将排序应用于您想要的内容。

$last之间的区别和 $max是后者将为分组 _id 中的给定字段选择“最高”值,无论当前按未排序顺序排序。另一方面,$last将选择与“最后一个”分组 _id 值出现在同一“行”中的值。


如果您实际上想要对数组的值进行排序,那么方法是类似的。将数组成员保持在“创建”顺序,您还需要首先排序:

db.mycollection.aggregate([

    // Sorts everything first by _id and created
    { "$sort": { "_id": 1, "created": 1 } },

    // Group with the $last results from each boundary
    { "$group": {
        "_id": "$uid",
        "row": {
            "$push": {
                "created": "$created",
                "another_col": "$another_col"
            }
        }
    }}
])

包含这些字段的文档将按照它们已排序的顺序添加到数组中。

关于mongodb - 如何使用group by进行聚合并正确排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23899409/

相关文章:

javascript - 使用 javascript 循环有效返回数据

json - MongoDB 在具有未知键的集合中查找

mongodb - 嵌入与链接

MongoDB 聚合 - 在单个查询中以 2 种方式分组

python - 如何从mongodb中获取匹配的子文档?

mongodb - 如何在 MongoDB 中填充嵌套的引用数组?

angularjs - 当我尝试从 Angular.js 发送到 Node.js 时,数据单独丢失

javascript - 如何将 NOT (A AND B) 转换为 mongodb 查询

node.js - 排除嵌套对象中的 Mongoose 表字段

java - MongoDB 聚合到 Java