MongoEngine(flask)不会正确排序(通过聚合) - 时不时

时间:2017-10-16 08:41:43

标签: python mongodb mongoengine flask-mongoengine

尝试按两个字段排序,优先考虑第一个 - 但在大多数情况下,似乎优先考虑第二个(lastName)。偶尔,它可以正常工作 - 不确定是什么改变了。

使用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)

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

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"
    }
]

使用db version 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"),
}

1 个答案:

答案 0 :(得分:0)

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

所以你想把你的$match放在你的管道的开头(接着是$sort),不管怎么说这都是出于性能原因的好主意。