我为我正在做的特定查询创建了几个项目的索引:
{
"v" : 1,
"key" : {
"MODIFIED" : -1,
"state" : 1,
"fail" : 1,
"generated" : 1
},
"ns" : "foo.bar",
"name" : "MODIFIED_-1_state_1_fail_1_generated"
}
然而,当我执行我的查询时,它并不是使用我的索引。你能不能对我做错了怎么说?
谢谢!
db.foo.find( {
"$or": [
{
"MODIFIED": {
"$gt": {
"sec": 1321419600,
"usec": 0
}
}
},
{
"$or": [
{"state": "ca"},
{"state": "ok"}
]
}
],
"$and": [
{"fail": {"$ne": 1}},
{"generated": {"$exists": false}}
]
}).explain();
{
"cursor" : "BasicCursor",
"nscanned" : 464215,
"nscannedObjects" : 464215,
"n" : 0,
"millis" : 7549,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
答案 0 :(得分:7)
有一个很好的理由你的索引不能用于你的查询,我也认为查询本身存在一些问题。它没有达到索引的原因是因为嵌套的$或运算符,但我认为你的实际问题是对MongoDB中可用的所有运算符缺乏了解:
首先,您的嵌套$或检查状态是“ca”还是“ok”是不必要的(因为这是您没有命中索引的主要原因)可以替换为{{1这完全相同的事情。现在您的查询是:
state:{$in:["ca", "ok"]}
它会击中你的指数。你的第二个问题是没有必要使用顶级$和子句。请注意db.foo.find( {
"$or": [
{
"MODIFIED": {
"$gt": {
"sec": 1321419600,
"usec": 0
}
}
},
{
state:{$in:["ca", "ok"]}
}
],
"$and": [
{"fail": {"$ne": 1}},
{"generated": {"$exists": false}}
]
}).explain();
。此查询也是如此:
AND(OR(A, B), AND(C, D)) = AND(OR(A, B), C, D)
哪个仍然符合索引:
db.foo.find( {
"$or": [
{
"MODIFIED": {
"$gt": {
"sec": 1321419600,
"usec": 0
}
}
},
{
state:{$in:["ca", "ok"]}
}
],
"fail": {"$ne": 1},
"generated": {"$exists": false}
}).explain();
希望有所帮助!顺便说一句,在你的复合索引中使用order 1启动第一个键并且使用-1来启动第二个键稍微更常规。请注意,-1仅用于确定相对于前一个字段的方向。