MongoDB:与Aggregation组一起排序

时间:2015-09-30 11:12:56

标签: mongodb sorting

我有一个名为 transaction 的集合,其中包含以下文档,

/* 0 */
{
    "_id" : ObjectId("5603fad216e90d53d6795131"),
    "statusId" : "65c719e6727d",
    "relatedWith" : "65c719e67267",
    "status" : "A",
    "userId" : "100",
    "createdTs" : ISODate("2015-09-24T13:15:36.609Z")
}

/* 1 */
{
    "_id" : ObjectId("5603fad216e90d53d6795134"),
    "statusId" : "65c719e6727d",
    "relatedWith" : "65c719e6726d",
    "status" : "B",
    "userId" : "100",
    "createdTs" : ISODate("2015-09-24T13:14:31.609Z")
}

/* 2 */
{
    "_id" : ObjectId("5603fad216e90d53d679512e"),
    "statusId" : "65c719e6727d",
    "relatedWith" : "65c719e6726d",
    "status" : "C",
    "userId" : "100",
    "createdTs" : ISODate("2015-09-24T13:13:36.609Z")
}

/* 3 */
{
    "_id" : ObjectId("5603fad216e90d53d6795132"),
    "statusId" : "65c719e6727d",
    "relatedWith" : "65c719e6726d",
    "status" : "D",
    "userId" : "100",
    "createdTs" : ISODate("2015-09-24T13:16:36.609Z")
}

当我在没有Aggregation的情况下运行以下$group查询时,

db.transaction.aggregate([
    {
        "$match": {
            "userId": "100",
            "statusId": "65c719e6727d"
        }
    },
    {
        "$sort": {
            "createdTs": -1
        }
    }
])

我得到预期排序顺序的结果。即按降序对createdTs进行排序(最小结果)

/* 0 */
{
    "result" : [ 
        {
            "_id" : ObjectId("5603fad216e90d53d6795132"),
            "createdTs" : ISODate("2015-09-24T13:16:36.609Z")
        }, 
        {
            "_id" : ObjectId("5603fad216e90d53d6795131"),
            "createdTs" : ISODate("2015-09-24T13:15:36.609Z")
        }, 
        {
            "_id" : ObjectId("5603fad216e90d53d6795134"),
            "createdTs" : ISODate("2015-09-24T13:14:31.609Z")
        }, 
        {
            "_id" : ObjectId("5603fad216e90d53d679512e"),
            "createdTs" : ISODate("2015-09-24T13:13:36.609Z")
        }
    ],
    "ok" : 1
}

如果我将下面的聚合应用于$group,则结果将按顺序排序(即升序排序)

db.transaction.aggregate([
    {
        "$match": {
            "userId": "100",
            "statusId": "65c719e6727d"
        }
    },
    {
        "$sort": {
            "createdTs": -1
        }
    },
    {
        $group: {
                "_id": {
                    "statusId": "$statusId",
                    "relatedWith": "$relatedWith",
                    "status": "$status"
                },
                "status": {$first: "$status"}, 
                "statusId": {$first: "$statusId"},
                "relatedWith": {$first: "$relatedWith"},
                "createdTs": {$first: "$createdTs"}
        }
    }
]);

我得到逆序的结果,即**按升序排序createdTs

/* 0 */
{
    "result" : [ 
        {
            "_id" : ObjectId("5603fad216e90d53d679512e"),
            "createdTs" : ISODate("2015-09-24T13:13:36.609Z")
        }, 
        {
            "_id" : ObjectId("5603fad216e90d53d6795134"),
            "createdTs" : ISODate("2015-09-24T13:14:31.609Z")
        }, 
        {
            "_id" : ObjectId("5603fad216e90d53d6795131"),
            "createdTs" : ISODate("2015-09-24T13:15:36.609Z")
        }, 
        {
            "_id" : ObjectId("5603fad216e90d53d6795132"),
            "createdTs" : ISODate("2015-09-24T13:16:36.609Z")
        }
    ],
    "ok" : 1
}

我哪里错了?

2 个答案:

答案 0 :(得分:1)

$ group阶段不保证结果的排序。见here第一段。 如果您希望在$ group之后对结果进行排序,则需要在$ group阶段之后添加$ sort

在你的情况下,你应该在$ group之后移动$ sort并在你提出问题之前:不,$ sort将无法在$ group之后使用索引,就像它之前那样$ group : - )。

$ group的内部算法似乎保持某种排序(显然是反转),但我不会指望它并添加$ sort。

答案 1 :(得分:1)

你这里没有做错任何事,它是Mongodb中的$ group行为

让我们看看这个例子

假设您在集合中有以下文档

{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }
{ "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }
{ "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") }
{ "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") }
{ "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }

现在如果你运行这个

db.collection.aggregate([{ $sort: { item: 1,date:1}} ] )

输出将按项目和日期的升序排列。

现在,如果在聚合管道中添加组阶段,它将颠倒顺序。

db.collection.aggregate([{ $sort: { item: 1,date:1}},{$group:{_id:"$item"}} ] ) 

输出

{ "_id" : "xyz" }
{ "_id" : "jkl" }
{ "_id" : "abc" }
  

现在解决您的问题

将“createdTs”更改为:-1到“createdTs”:1表示组