MongoDB - 降序索引奇怪的行为

时间:2014-02-11 23:07:13

标签: mongodb mongodb-query

我的test数据库中有这个test集合。

[test] 2014-02-11 18:01:33.970 >>> db.test.find ();
{ "_id" : ObjectId("52faa8a695fa10cc7d2b7908"), "x" : 1 }
{ "_id" : ObjectId("52faa8ab95fa10cc7d2b7909"), "x" : 5 }
{ "_id" : ObjectId("52faa8ad95fa10cc7d2b790a"), "x" : 15 }
{ "_id" : ObjectId("52faa8b095fa10cc7d2b790b"), "x" : 25 }
{ "_id" : ObjectId("52faa8b795fa10cc7d2b790c"), "x" : [ 5, 25 ] }

如果我使用

在x字段上创建升序索引
[test] 2014-02-11 18:01:50.615 >>> db.test.createIndex({x : 1});

然后这个查找查询工作正常并返回预期结果:

[test] 2014-02-11 18:01:48.72 >>> db.test.find ( { x : {$gt: 10, $lt: 20} } ).min({x:10}).max({x:20});
{ "_id" : ObjectId("52faa8ad95fa10cc7d2b790a"), "x" : 15 }
[test] 2014-02-11 18:01:50.615 >>>

如果删除升序索引,则为Buf,然后使用

创建降序索引
[test] 2014-02-11 18:01:50.615 >>> db.test.createIndex({x : -1});

然后相同的查询返回此错误:

error: {
        "$err" : "no index found for specified keyPattern: {} min: { x: 10.0 } max: { x: 20.0 }",
        "code" : 10367
}

我期待MongoDB会在这里返回相同的文档:

{ "_id" : ObjectId("52faa8ad95fa10cc7d2b790a"), "x" : 15 }      

这对我来说听起来不合逻辑 这是为什么?为什么MongoDB无法在x上使用该降序索引?

create index
drop index
get indexes

2 个答案:

答案 0 :(得分:3)

这对我有用:

> db.h.insert({x:15})
> db.h.createIndex({x:-1})
> db.h.find().min({x:20}).max({x:10})
{ "_id" : ObjectId("52fb6930253ac3dcf43b27f5"), "x" : 15 }

您的索引可能有问题。

这种方法起作用的原因是因为索引是另一种方式。

想象一下你在它的头上转了一个列表,min和max有效地说是获得该列表的范围,其中min为10且max为20.但是由于列表是颠倒的,所以该范围不再存在。相反,必须反转范围以匹配列表。

答案 1 :(得分:1)

要回答你的问题,这根本不奇怪(如果你真的看看你在做什么,你好像在问很多问题,说明“奇怪”的行为)。

正如您所说将您的索引的顺序更改为降序。因此,让我们分阶段查看查询结果:

> db.test.find ( { x : {$gt: 10, $lt: 20} } )
{ "_id" : ObjectId("52faa8b795fa10cc7d2b790c"), "x" : [  5,  25 ] }
{ "_id" : ObjectId("52faa8ad95fa10cc7d2b790a"), "x" : 15 }

因此,您的第一个结果是唯一符合您条件的文档。那么让我们看一下下一阶段以及解释的输出:

> db.test.find ( { x : {$gt: 10, $lt: 20} } ).min({x :10})
{ "_id" : ObjectId("52faa8b795fa10cc7d2b790c"), "x" : [  5,  25 ] }
> db.test.find ( { x : {$gt: 10, $lt: 20} } ).min({x :10}).explain()
{
    "cursor" : "BtreeCursor x_-1",
    "isMultiKey" : true,
    "n" : 1,
    "nscannedObjects" : 3,
    "nscanned" : 3,
    "nscannedObjectsAllPlans" : 3,
    "nscannedAllPlans" : 3,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
            "start" : {
                    "x" : 10
            },
            "end" : {
                    "x" : {
                            "$minElement" : 1
                    }
            }
    },
    "server" : "ubuntu:27017"
}

在这里,我们可以看到包含 x 数组值的行的结果。这是您需要查看解释输出中显示的indexBounds的重要部分。您可以看到边界从10开始,这是您的请求,并以数组元素的最小结果结束。尽管您在文档中缺乏预测,但实际上已经给出了答案, 5

因此,当您再次开始修改,查找indexBounds之外的结果时,查询将 boom 。你搞砸了,并要求一些不存在的东西。

现在,如果您期待将结果取回:

{ "_id" : ObjectId("52faa8b795fa10cc7d2b790c"), "x" : [  25 ] }

答案是,事情就是这样。如上所述,您已经在第一个 min 操作中减少了该设置。已经完成了。