没有使用Mongo索引

时间:2012-02-14 16:31:12

标签: mongodb

我为我正在做的特定查询创建了几个项目的索引:

{
    "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" : {

    }
}

1 个答案:

答案 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仅用于确定相对于前一个字段的方向。