【问题标题】:MongoEngine (flask) does not sort (via aggregate) correctly - every now and thenMongoEngine(烧瓶)不正确排序(通过聚合) - 不时
【发布时间】:2017-10-16 08:41:42
【问题描述】:

尝试按两个字段排序,优先考虑第一个 - 但在大多数情况下,似乎优先考虑第二个(姓氏)。有时,它可以正常工作 - 不确定是什么导致了这种变化。

使用 Robo3t 作为客户端,连接相同的数据库,同样的命令也能正常工作。

运行 Flask 并使用 Mongoengine,代码如下:

pipeline = [{"$sort": {"importance": -1, "lastName": 1}}, {"$match": {"visible": True, "editionId": "2017"}},
            {"$project": {'firstName': 1, 'lastName': 1, 'biography': 1, 'position': 1, 'workAt': 1, '_id': 0,
                          "imageUrl": 1}}]
doc = Speakers.objects.aggregate(*pipeline)

在 Robo3t 中,相同的代码('True' 变为 'true' 除外):

db.getCollection('speakers').aggregate([{"$sort": {"importance": -1, "lastName": 1}}, {"$match": {"visible": true, "editionId": "2017"}},
            {"$project": {'firstName': 1, 'lastName': 1, 'biography': 1, 'position': 1, 'workAt': 1, '_id': 0,
                          "imageUrl": 1}}], {"collation": {"locale": "en"}}
      )

mongodb (3.4.9) 上的索引如下所示:

> db.speakers.getIndexes()
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "website_v3.speakers"
    }
]

使用数据库版本 v3.4.9

我什至尝试过为重要性创建一个索引(排序规则),但结果完全一样。首先它起作用,然后它不起作用。

欢迎任何想法!

编辑:

flask_mongoengine 似乎弄乱了 $sort 和 $project 的顺序。

mongo
> db.system.profile.find().pretty()
{
    "op" : "query",
    "ns" : "website_v3.system.profile",
    "query" : {
        "find" : "system.profile",
        "filter" : {

        }
    },
    "keysExamined" : 0,
    "docsExamined" : 0,
    "cursorExhausted" : true,
    "numYield" : 0,
    "locks" : {
        "Global" : {
            "acquireCount" : {
                "r" : NumberLong(2)
            }
        },
        "Database" : {
            "acquireCount" : {
                "r" : NumberLong(1)
            }
        },
        "Collection" : {
            "acquireCount" : {
                "r" : NumberLong(1)
            }
        }
    },
    "nreturned" : 0,
    "responseLength" : 98,
    "protocol" : "op_command",
    "millis" : 0,
    "planSummary" : "COLLSCAN",
    "execStats" : {
        "stage" : "COLLSCAN",
        "nReturned" : 0,
        "executionTimeMillisEstimate" : 0,
        "works" : 2,
        "advanced" : 0,
        "needTime" : 1,
        "needYield" : 0,
        "saveState" : 0,
        "restoreState" : 0,
        "isEOF" : 1,
        "invalidates" : 0,
        "direction" : "forward",
        "docsExamined" : 0
    },
    "ts" : ISODate("2017-10-19T20:55:30.415Z"),

}
{
    "op" : "command",
    "ns" : "website_v3.speakers",
    "command" : {
        "aggregate" : "speakers",
        "pipeline" : [
            {
                "$match" : {
                    "visible" : true,
                    "editionId" : "2017"
                }
            },
            {
                "$sort" : {
                    "lastName" : 1,
                    "importance" : -1
                }
            },
            {
                "$project" : {
                    "firstName" : 1,
                    "position" : 1,
                    "biography" : 1,
                    "workAt" : 1,
                    "imageUrl" : 1,
                    "_id" : 0,
                    "lastName" : 1
                }
            }
        ],
        "cursor" : {

        }
    },
    "cursorid" : 168077246844,
    "keysExamined" : 0,
    "docsExamined" : 541,
    "hasSortStage" : true,
    "numYield" : 4,
    "locks" : {
        "Global" : {
            "acquireCount" : {
                "r" : NumberLong(16)
            }
        },
        "Database" : {
            "acquireCount" : {
                "r" : NumberLong(8)
            }
        },
        "Collection" : {
            "acquireCount" : {
                "r" : NumberLong(7)
            }
        }
    },
    "nreturned" : 101,
    "responseLength" : 157635,
    "protocol" : "op_query",
    "millis" : 2,
    "planSummary" : "COLLSCAN",
    "ts" : ISODate("2017-10-19T20:55:57.691Z"),
}
{
    "op" : "getmore",
    "ns" : "website_v3.speakers",
    "query" : {
        "getMore" : NumberLong("168077246844"),
        "collection" : "speakers"
    },
    "originatingCommand" : {
        "aggregate" : "speakers",
        "pipeline" : [
            {
                "$match" : {
                    "visible" : true,
                    "editionId" : "2017"
                }
            },
            {
                "$sort" : {
                    "lastName" : 1,
                    "importance" : -1
                }
            },
            {
                "$project" : {
                    "firstName" : 1,
                    "position" : 1,
                    "biography" : 1,
                    "workAt" : 1,
                    "imageUrl" : 1,
                    "_id" : 0,
                    "lastName" : 1
                }
            }
        ],
        "cursor" : {

        }
    },
    "cursorid" : 168077246844,
    "keysExamined" : 0,
    "docsExamined" : 0,
    "hasSortStage" : true,
    "cursorExhausted" : true,
    "numYield" : 0,
    "locks" : {
        "Global" : {
            "acquireCount" : {
                "r" : NumberLong(4)
            }
        },
        "Database" : {
            "acquireCount" : {
                "r" : NumberLong(2)
            }
        },
        "Collection" : {
            "acquireCount" : {
                "r" : NumberLong(2)
            }
        }
    },
    "nreturned" : 204,
    "responseLength" : 303603,
    "protocol" : "op_query",
    "millis" : 0,
    "planSummary" : "COLLSCAN",
    "ts" : ISODate("2017-10-19T20:55:57.702Z"),
}

【问题讨论】:

    标签: python mongodb mongoengine flask-mongoengine


    【解决方案1】:

    MongoDB 将按照您指定的确切顺序执行聚合阶段(在大多数情况下)。 $match 运算符不保证输出顺序。

    因此,您可能希望将 $match 放在管道的开头(后面是 $sort),出于性能原因,这无论如何都是一个好主意。

    【讨论】:

    • 我尝试按照您的建议输入$match 然后$sort,但得到相同的结果。项目按lastName 而非importance 排序。奇怪的是,无论哪种方式,它在 Robo3T 中都能正常工作。
    • 我建议您在服务器端记录您的查询并进行比较。如果烧瓶与可以解释它的查询混淆。但是,如果使用 Robo3T 和您的应用程序记录了完全相同的查询,那么问题一定出在其他地方:stackoverflow.com/questions/15204341/…
    • 其他潜在的混淆来源可能是排序规则设置、混合字段类型(例如重要性的 int 和字符串)、空值、值开头的多余空格字符或字段名称中的拼写错误。最后,您可能想测试其他排序方式,例如仅使用find() 或不使用其他两个阶段来隔离问题。
    • 另外,我想知道,您如何检测不正确的排序 - 您的应用程序中的任何操作是否会对检索到的数据执行可能会更改顺序的操作?
    猜你喜欢
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多