Mongodb 将在两个不同的时间执行排序。
- 查询时间(该字段没有索引)
- 索引时间。 (当我们创建索引时)
因此,对于相同的查询,您会得到不同的结果。
无索引:
当我们在 mongodb 中执行排序(排序字段上没有索引)时,将在查询时通过扫描整个集合开始对集合进行排序。
排序的方向将是向前的(偶数标记:-1),即它将首先接触文档的插入顺序(_id 值)。
当遇到两个具有相同字段的文档(标记:两个文档为空)时,它会按照它们的_id值排列它们。
带索引:
您按升序在标记字段上创建了索引(索引只不过是生成以键为标记的 B-tree)。
当我们尝试使用marks:1 对集合进行排序时,我们将按索引顺序获得相同的结果。
当我们尝试使用标记对集合进行排序时:-1 然后 mongodb 将开始从向后返回文档,因为文档已经按升序索引(排序)。
这就是我们得到不同结果的原因。
当您对它们执行explain() 时,您可以获得有关这些查询的更多详细信息。
无索引:
db.students2.find().sort({marks:-1}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "stackoverflow.students2",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [ ]
},
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"marks" : -1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"$and" : [ ]
},
"direction" : "forward"
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "sys2030",
"port" : 27017,
"version" : "3.2.22",
"gitVersion" : "105adca0d443f9a1a5abd608fd7133840a68dd"
},
"ok" : 1
}
我们没有索引,所以 mongodb 在查询时开始扫描它。
带索引:
db.students.find().sort({marks:-1}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "stackoverflow.students",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [ ]
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"marks" : 1
},
"indexName" : "marks_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "backward",
"indexBounds" : {
"marks" : [
"[MaxKey, MinKey]"
]
}
}
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "sys2030",
"port" : 27017,
"version" : "3.2.22",
"gitVersion" : "105adca0d443f9a1a5abd608fd7133840a68dd"
},
"ok" : 1
}
我们有 index ,所以 mongodb 开始使用它并简单地从 backs(marks:-1) 返回结果。
这就是我们在collection很大的时候进行排序的原因,monogodb会报错:sort with large amount of data , without index。
进一步阅读:
https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/
https://docs.mlab.com/indexing/