Mongo ObjectId 如何在内部进行比较?
How is Mongo ObjectId Compared Internally?
TLDR:当运行 Mongo Shell命令时,ObjectId("LowerCaseHexString")
和ObjectId("UpperCaseHexString")
没有区别。
只是我的一个粗心错误...
原Qn:
我刚刚注意到一些 非常 奇怪的行为,同时执行几个命令,删除子中的一些数组元素文档,在 Mongo Shell.
这与构造对象 ID 时是否使用 大写 或 小写 十六进制字符串有关,即 ObjectId("UpperOrLowerCaseString")
首先,这两个查询 return 文档:
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")}})
这是意料之中的。 HOWEVER 当尝试 $pull
子文档中的元素时,以下查询有效:
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 字节形式。
希望这不是我的错误(很容易犯这些错误)...
但是有人愿意透露一些信息吗?特别是关于我的 findOne
和 update
查询之间的行为不一致?
如果确实将完整的字符串值用于比较,那么这不是非常令人担忧的性能明智吗? IE。每次比较 24 个字节而不是 12 个?
使用相同十六进制值的小写或大写版本所产生的 ObjectID 没有区别。您看到不同的结果,因为您在这两种情况下使用了不同的十六进制值:
ObjectId("54b4ef540000000000000000")
... ^^
ObjectId("54B4EDC40000000000000000")
TLDR:当运行 Mongo Shell命令时,ObjectId("LowerCaseHexString")
和ObjectId("UpperCaseHexString")
没有区别。
只是我的一个粗心错误...
原Qn:
我刚刚注意到一些 非常 奇怪的行为,同时执行几个命令,删除子中的一些数组元素文档,在 Mongo Shell.
这与构造对象 ID 时是否使用 大写 或 小写 十六进制字符串有关,即 ObjectId("UpperOrLowerCaseString")
首先,这两个查询 return 文档:
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")}})
这是意料之中的。 HOWEVER 当尝试 $pull
子文档中的元素时,以下查询有效:
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 字节形式。
希望这不是我的错误(很容易犯这些错误)...
但是有人愿意透露一些信息吗?特别是关于我的 findOne
和 update
查询之间的行为不一致?
如果确实将完整的字符串值用于比较,那么这不是非常令人担忧的性能明智吗? IE。每次比较 24 个字节而不是 12 个?
使用相同十六进制值的小写或大写版本所产生的 ObjectID 没有区别。您看到不同的结果,因为您在这两种情况下使用了不同的十六进制值:
ObjectId("54b4ef540000000000000000")
... ^^
ObjectId("54B4EDC40000000000000000")