复合索引不可用于反向排序,但不必担心在这种情况下它可能无济于事,如果你在 $mendor["t"] 中有一个真实的列表。我用简单的文档制作了一个名为 t 的测试集合,例如:
{ "_id" : ObjectId("51a4c2c75e0733e8428ab2c0"), "x" : [ 1, 2, 3, 4 ] }
{ "_id" : ObjectId("51a4c2c95e0733e8428ab2c1"), "x" : [ 1, 2, 3, 6 ] }
{ "_id" : ObjectId("51a4c2cd5e0733e8428ab2c2"), "x" : [ 1, 4, 3, 6 ] }
我创建了索引:x_1__id_1
对于查询:
db.t.find({x:3}).hint("x_1__id_1").sort({_id:1}).explain()
{
"cursor" : "BtreeCursor x_1__id_1",
"isMultiKey" : true,
"n" : 14,
"nscannedObjects" : 14,
"nscanned" : 14,
"nscannedObjectsAllPlans" : 14,
"nscannedAllPlans" : 14,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"x" : [
[
3,
3
]
],
"_id" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : ""
}
因此,它可以按照您喜欢的查询工作,但是:
db.t.find({x:{$in:[3,4]}}).hint("x_1__id_1").sort({_id:1}).explain()
{
"cursor" : "BtreeCursor x_1__id_1 multi",
"isMultiKey" : true,
"n" : 16,
"nscannedObjects" : 28,
"nscanned" : 28,
"nscannedObjectsAllPlans" : 28,
"nscannedAllPlans" : 28,
"scanAndOrder" : true,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"x" : [
[
3,
3
],
[
4,
4
]
],
"_id" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : ""
}
这是合理的,而使用的多键索引将数组中的值作为单独的索引键存储。请参阅文档:http ://docs.mongodb.org/manual/core/indexes/#multikey-indexes
因此,从不同键收集的不同部分将由引擎合并并排序。如果您使用类似于我的第一个查询的条件,那么只需搜索一个值而不是数组。比它会 scanAndOrder : false。可能您必须创建一个 x_1_ id -1 索引。
有一种解决方法,但它有点难看。如果您对查询使用 or 子句,那么 or 列表的每个部分都将单独使用索引。因此,不要使用 in:[] 条件,而是使用 or:[] 并定义与 $mendor["t"] 数组中的值一样多的不同查询。在 mongoshell 中没有用,但我相信它应该,也许我错过了一些东西。