为什么 PyMongo 将 uuid.uuid1() 编码为 BSON::Binary?

zak*_*ces 2 python uuid mongodb bson pymongo

我正在为 Mongo 中的所有文档添加一个值为 uuid.uuid1() (来自 python uuid 模块)的“GUID”键。我注意到它们不是存储为字符串,而是存储为BSON::Binary类型。我已经做了一些谷歌搜索,但我仍然不明白这个序列化的目的/优点是什么。有人可以解释一下吗?我应该在存储之前将 uuid.uuid1() 转换为字符串吗?如何使用字符串通过 GUID 值来 find(),例如 db.myCol.find({ 'GUID' : aString })?

Ste*_*nie 5

Python 的默认序列化uuid使用BSON 规范UUID中的二进制表示形式,因为这可以确保范围查询的排序一致,并且还可以使用更少的数据/索引存储。

例如,这三个字符串在十六进制中是等效的:

5d78ad35ea5f11e1a183705681b29c47
5D78AD35EA5F11E1A183705681B29C47
5d78ad35ea5f11e1A183705681B29C47
Run Code Online (Sandbox Code Playgroud)

..但具有不同的字符串排序顺序:

> db.uuidsort.find().sort({_id:1})
{ "_id" : "5D78AD35EA5F11E1A183705681B29C47" }
{ "_id" : "5d78ad35ea5f11e1A183705681B29C47" }
{ "_id" : "5d78ad35ea5f11e1a183705681b29c47" }
Run Code Online (Sandbox Code Playgroud)

比较 bson 大小:

> db.uuidtest.find()
{ "_id" : BinData(3,"XXitNepfEeGhg3BWgbKcRw==") }
{ "_id" : "5d78ad35ea5f11e1a183705681b29c47" }

> Object.bsonsize(db.uuidtest.findOne({_id: BinData(3,"XXitNepfEeGhg3BWgbKcRw==")}))
31

> Object.bsonsize(db.uuidtest.findOne({_id: "5d78ad35ea5f11e1a183705681b29c47"}))
47
Run Code Online (Sandbox Code Playgroud)

如果您确实想作为字符串插入,可以使用UUID.hex获取等效的 32 字符字符串:

>>> db.uuidtest.insert({'_id': uuid.hex})
'5d78ad35ea5f11e1a183705681b29c47'
Run Code Online (Sandbox Code Playgroud)

如果你想从Python中通过字符串查找UUID,你可以使用uuid.UUID方法:

>>> db.uuidtest.find_one({'_id':uuid.UUID('5d78ad35ea5f11e1a183705681b29c47')})
{u'_id': UUID('5d78ad35-ea5f-11e1-a183-705681b29c47')}
Run Code Online (Sandbox Code Playgroud)

如果你想从 shell 中通过字符串查找 UUID mongo,有一个UUID()帮助器:

> db.uuidtest.find({_id:UUID('5d78ad35ea5f11e1a183705681b29c47')})
{ "_id" : BinData(3,"XXitNepfEeGhg3BWgbKcRw==") }
Run Code Online (Sandbox Code Playgroud)

注意:还有一些其他 UUID 子类型可用于与其他驱动程序版本的互操作性,如bson.binary 的 API 文档中所述。