Mongo聚合框架无法按两个字段排序?

时间:2014-04-02 16:47:29

标签: mongodb sorting pymongo aggregation-framework

我正在对mongo 2.4.9集合进行一些聚合,但我无法通过两个字段对结果进行排序。这是我使用PyMongo进行的查询:

result = mongo_coll.aggregate([{"$match": {"_cls": "class1"},
                               {"$group": {"_id": {"currency": "$total.currency",
                                                   "v_id": "$v_id"},
                                           "total": {"$sum": "$total.amount"},
                                           "count": {"$sum": 1}}},
                               {"$sort": {"_id.currency": 1, "total": -1}}])

我的结果按“总计”排序: - 1

如果我用以下内容替换最后一行:

                               {"$sort": {"total": -1, "_id.currency": 1}}])

它仍按“总计”排序: - 1

如果我用以下内容替换它:

                               {"$sort": {"_id.currency": 1}}])

按货币排序。

但我无法按照我想要的方式对其进行排序,这意味着首先是货币,然后是总数......(其他结果看起来很好,正如预期的那样)。有人有线索吗?

最好并提前致谢!

更新:这是一个示例文档:

{
  "_id": { "$oid" : "533d0a3b830f783478a75aa1" },
  "_cls": "class1",
  "v_id": 6813,
  "total": {
    "amount": 680,
    "currency": "EUR",
    "exp": -2
  }
}

2 个答案:

答案 0 :(得分:10)

由于MongieDB用户Google Group中Bernie的回答,我实际上可以找到为什么会发生这种情况的原因:

Python dict是无序的,这对于进行排序非常合理:-p

这就是为什么参数可以作为BSON.SON dictOrderedDict给出,以使其更加pythonic!

以下是我使用的解决方案:

    from collections import OrderedDict
    sort_dict = OrderedDict()
    sort_dict['_id.currency'] = 1
    sort_dict['total'] = -1

然后

{"$sort": sort_dict}

修改 来自Google用户组中的response的链接...

答案 1 :(得分:0)

如果您希望按货币首先进行排序,则应将排序更改为 - {"$sort": {"_id.currency": 1, "total": -1}}。排序顺序由您指定键的顺序驱动。

这些是我创建的示例文档 -

{ "_id" : ObjectId("533dc9d272337e43d14600f7"), "_cls" : "class1", "v_id" : 6813, "total" : { "amount" : 680, "currency" : "EUR", "exp" : -2 } }
{ "_id" : ObjectId("533dc9d972337e43d14600f8"), "_cls" : "class1", "v_id" : 6813, "total" : { "amount" : 690, "currency" : "EUR", "exp" : -2 } }
{ "_id" : ObjectId("533dc9de72337e43d14600f9"), "_cls" : "class1", "v_id" : 6813, "total" : { "amount" : 690, "currency" : "USD", "exp" : -2 } }
{ "_id" : ObjectId("533dc9e672337e43d14600fa"), "_cls" : "class1", "v_id" : 6813, "total" : { "amount" : 680, "currency" : "USD", "exp" : -2 } }
{ "_id" : ObjectId("533dcd0172337e43d14600fb"), "_cls" : "class1", "v_id" : 6813, "total" : { "amount" : 2000, "currency" : "CHE", "exp" : -2 } }
{ "_id" : ObjectId("533dcdfb72337e43d14600fc"), "_cls" : "class1", "v_id" : 6814, "total" : { "amount" : 2000, "currency" : "CHE", "exp" : -2 } }
{ "_id" : ObjectId("533dce1572337e43d14600fd"), "_cls" : "class1", "v_id" : 6815, "total" : { "amount" : 1000, "currency" : "CHE", "exp" : -2 } }

用于查询 - db.sample4.aggregate([{"$match": {"_cls": "class1"}},{$group:{"_id":{"currency":"$total.currency","v_id":"$v_id"},"total":{$sum:"$total.amount"}}},{"$sort": {"_id.currency": 1, "total": -1}}])输出为 -

{
    "result" : [
        {
            "_id" : {
                "currency" : "CHE",
                "v_id" : 6814
            },
            "total" : 2000
        },
        {
            "_id" : {
                "currency" : "CHE",
                "v_id" : 6813
            },
            "total" : 2000
        },
        {
            "_id" : {
                "currency" : "CHE",
                "v_id" : 6815
            },
            "total" : 1000
        },
        {
            "_id" : {
                "currency" : "EUR",
                "v_id" : 6813
            },
            "total" : 1370
        },
        {
            "_id" : {
                "currency" : "USD",
                "v_id" : 6813
            },
            "total" : 1370
        }
    ],
    "ok" : 1
}
查询db.sample4.aggregate([{"$match": {"_cls": "class1"}},{$group:{"_id":{"currency":"$total.currency","v_id":"$v_id"},"total":{$sum:"$total.amount"}}},{"$sort": {"_id.currency": 1, "total": 1}}])输出的

是 -

{
    "result" : [
        {
            "_id" : {
                "currency" : "CHE",
                "v_id" : 6815
            },
            "total" : 1000
        },
        {
            "_id" : {
                "currency" : "CHE",
                "v_id" : 6814
            },
            "total" : 2000
        },
        {
            "_id" : {
                "currency" : "CHE",
                "v_id" : 6813
            },
            "total" : 2000
        },
        {
            "_id" : {
                "currency" : "EUR",
                "v_id" : 6813
            },
            "total" : 1370
        },
        {
            "_id" : {
                "currency" : "USD",
                "v_id" : 6813
            },
            "total" : 1370
        }
    ],
    "ok" : 1
}