尝试按两个字段排序,优先考虑第一个 - 但在大多数情况下,似乎优先考虑第二个(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"),
}
答案 0 :(得分:0)
MongoDB将按照您指定的确切顺序执行聚合阶段(在大多数情况下)。 $match
运算符不保证输出顺序。
所以你想把你的$match
放在你的管道的开头(接着是$sort
),不管怎么说这都是出于性能原因的好主意。