Is it possible to reverse the traversing order of index in MongoDB to keep performance but ingore creating similar index?

╄→尐↘猪︶ㄣ 提交于 2020-01-06 08:51:06

问题


Collection c has hundred thousands of documents, and every document has two fields (x and y). Below are some examples.

{ "_id" : ObjectId("53fecab45ae4ec5280a0736f"), "x" : 1, "y" : 1 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07370"), "x" : 2, "y" : 1 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07371"), "x" : 3, "y" : 1 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07372"), "x" : 3, "y" : 2 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07373"), "x" : 3, "y" : 3 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07374"), "x" : 4, "y" : 2 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07376"), "x" : 5, "y" : 1 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07377"), "x" : 5, "y" : 3 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07378"), "x" : 5, "y" : 5 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07379"), "x" : 6, "y" : 2 }
{ "_id" : ObjectId("53fecab45ae4ec5280a0737a"), "x" : 6, "y" : 4 }
{ "_id" : ObjectId("53fecab45ae4ec5280a0737b"), "x" : 6, "y" : 4 }
{ "_id" : ObjectId("53fecab45ae4ec5280a0737c"), "x" : 7, "y" : 3 }
{ "_id" : ObjectId("53fecab45ae4ec5280a0737d"), "x" : 8, "y" : 8 }
{ "_id" : ObjectId("53fecab45ae4ec5280a0737e"), "x" : 9, "y" : 3 }
{ "_id" : ObjectId("53fecab45ae4ec5280a0737f"), "x" : 9, "y" : 1 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07380"), "x" : 10, "y" : 11 }

The values of x and y is number type, but random. Now I want to find no more than 3 documents whose values are least but larger than or equal to {x:5, y:3}. Regulation to compare two documents by function:

int compareDocument(doc1, doc2) {
    var result;
    if (doc1.x > doc2.x) {
        result = 1;
    } else if (doc1.x == doc2.x) {
        if (doc1.y > doc2.y) {
            result = 1;
        } else if (doc1.y == doc2.y) {
            result = 0;
        } else {
            result = -1;
        }
    } else {
        result = -1;
    }
    return result;
}

It must be executed in high performance. The method I have is:

> db.c.ensureIndex({x:1,y:1},{name:"asc"});
> db.c.find().hint("asc").min({x:5,y:3}).limit(3);
{ "_id" : ObjectId("53fecab45ae4ec5280a07377"), "x" : 5, "y" : 3 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07378"), "x" : 5, "y" : 5 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07379"), "x" : 6, "y" : 2 }
> db.c.find().hint("asc").min({x:5,y:3}).limit(3).explain();
{
        "cursor" : "BtreeCursor asc",
        "isMultiKey" : false,
        "n" : 3,
        "nscannedObjects" : 3,
        "nscanned" : 3,
        "nscannedObjectsAllPlans" : 3,
        "nscannedAllPlans" : 3,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "start" : {
                        "x" : 5,
                        "y" : 3
                },
                "end" : {
                        "x" : {
                                "$maxElement" : 1
                        },
                        "y" : {
                                "$maxElement" : 1
                        }
                }
        },
        "server" : "Mars-PC:27017"
}

Above only 3 documents scanned.

Again, I want to find no more than 3 documents whose values are largest but less than or equal to {x:5, y:3}. Is it possible to do this by using above index asc, or something else without creating new index, but keep high perforance?

I can't find it. What I can do is to create another similar index to fultill it.

> db.c.ensureIndex({x:-1, y:-1},{name:"desc"});
> db.c.find().hint("desc").min({x:5, y:3}).limit(3);
{ "_id" : ObjectId("53fecab45ae4ec5280a07377"), "x" : 5, "y" : 3 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07376"), "x" : 5, "y" : 1 }
{ "_id" : ObjectId("53fecab45ae4ec5280a07374"), "x" : 4, "y" : 2 }
> db.c.find().hint("desc").min({x:5, y:3}).limit(3).explain();
{
        "cursor" : "BtreeCursor desc",
        "isMultiKey" : false,
        "n" : 3,
        "nscannedObjects" : 3,
        "nscanned" : 3,
        "nscannedObjectsAllPlans" : 3,
        "nscannedAllPlans" : 3,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "start" : {
                        "x" : 5,
                        "y" : 3
                },
                "end" : {
                        "x" : {
                                "$minElement" : 1
                        },
                        "y" : {
                                "$minElement" : 1
                        }
                }
        },
        "server" : "Mars-PC:27017"
}

来源:https://stackoverflow.com/questions/25539800/is-it-possible-to-reverse-the-traversing-order-of-index-in-mongodb-to-keep-perfo

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!