Mongo ObjectId如何在内部进行比较?

时间:2015-01-13 12:12:06

标签: mongodb mongodb-query

TLDR:运行Mongo Shell命令时,ObjectId("LowerCaseHexString")ObjectId("UpperCaseHexString")之间没有区别。

对我来说只是一个粗心的错误......

原版Qn:

我刚刚在Mongo Shell中执行了几个命令,删除子文档中的一些数组元素时,发现了一些 非常 的古怪行为。 / p>

这与构造对象ID时是否使用大写小写十六进制字符串有关,即ObjectId("UpperOrLowerCaseString")

首先,这两个查询都返回文档:

db.users.findOne({"id":1, "SubDoc._id":{$lt: ObjectId("54B4EF540000000000000000")}})
db.users.findOne({"id":1, "SubDoc._id":{$lt: ObjectId("54b4ef540000000000000000")}})

这两个都没有(注意$lt已被$gt替换):

db.users.findOne({"id":1, "SubDoc._id":{$gt: ObjectId("54B4EF540000000000000000")}})
db.users.findOne({"id":1, "SubDoc._id":{$gt: ObjectId("54b4ef540000000000000000")}})

预期。尝试从子文档中的$pull元素时 HOWEVER ,以下查询有效:

db.users.update(
    {"id":1}, 
    {$pull:
        {"SubDoc":
            {_id: {$lt: ObjectId("54b4ef540000000000000000")}}
        }
    }
)

虽然这不是(注意从小写到大写的变化):

db.users.update(
    {"id":1}, 
    {$pull:
        {"SubDoc":
            {_id: {$lt: ObjectId("54B4EDC40000000000000000")}}
        }
    }
)

有趣的是,这有效(注意$lt替换为$gt):

db.users.update(
    {"id":1}, 
    {$pull:
        {"SubDoc":
            {_id: {$gt: ObjectId("54B4EDC40000000000000000")}}
        }
    }
)

这使我相信在update的情况下,实际的字符串值用于比较对象id(由于字节表示,小写字符串更大)。

findOne的情况下,似乎不是这种情况,即在比较之前将对象ID转换为它们的12字节形式。

希望这对我来说不是一个错误(很容易出现这些错误)......

但是有人想关注一些事情吗?特别是我的findOneupdate查询之间的行为不一致?

如果确实将完整的字符串值用于比较,那么表现不是很令人担忧吗?即每次比较24个字节而不仅仅是12个字节?

1 个答案:

答案 0 :(得分:2)

使用相同十六进制值的小写或大写版本产生的ObjectID没有区别。您会看到不同的结果,因为您在两种情况下使用不同的十六进制值:

ObjectId("54b4ef540000000000000000")
...            ^^
ObjectId("54B4EDC40000000000000000")