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

8

我正在对一个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}}])

我把结果按“总计”排序并倒序排列:

如果我将最后一行替换为以下代码:

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

它仍按"total":-1进行排序。

如果我将其替换为以下内容:

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

这个内容是与IT技术有关的,它被按照货币进行排序。

但是我不能按我想要的方式进行排序,也就是先按货币排序,然后再按总额排列...(其他结果看起来还不错,如预期所示)。有人有线索吗?

最好并提前表示感谢!

更新:这里是一个样本文档:

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

currency 的数据类型是什么?你能发布一份你的收藏中的示例文档吗? - Anand Jayabalan
货币是一个StringField,我将在问题中提供一个示例文档进行更新。 - Rmatt
你能否发布一些样本输出,其中文档按照与您所期望的排序不同的方式进行排序(以及您在查询中指定的排序顺序)?在快速测试中,我无法重现您在MongoDB 2.4.9中遇到的问题。一个可能性是您有一些总计数可能是字符串而不是数字。 - Stennie
2个回答

10

多亏了 MongoDB 用户 Google Group 中 Bernie 的回答,我终于找到了这个问题发生的原因:

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

这就是为什么参数可以作为 BSON.SON dict 或者 OrderedDict 给出以保持更符合 Python 的风格!

这是我使用的解决方案:

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

并且,然后。
{"$sort": sort_dict}

编辑 来自谷歌用户组的回复链接...


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
}

1
我完全同意你的观点!这也是我开始的方式!问题在于,在我的集合中,使用完全相同的排序方式,它并没有按照这种方式排序,而是仅按 {"total": -1} 排序!!!这就是为什么我怀疑有一些错误。在匹配了几百万条记录后,我对几千条记录进行聚合排序。 - Rmatt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接