通用唯一标识符 (UUIDs)
本页内容
概述
MongoDB 驱动程序在如何编码 通用唯一标识符 (UUIDs) 方面一直存在差异。在本指南中,您可以了解如何使用 PyMongo 的UuidRepresentation
配置选项,以在使用 UUIDs 时保持跨语言兼容性。
提示
在 MongoDB 应用程序中,您可以使用 ObjectId
类型作为文档的唯一标识符。在可能的情况下,请考虑使用 ObjectId
替代 UUID。
mongodb UUIDs简史
考虑以下规范文本表示的UUID
00112233-4455-6677-8899-aabbccddeeff
最初,MongoDB将UUID表示为BSON Binary
子类型3的值。因为子类型3在编码期间没有标准化UUID的字节序,所以不同的MongoDB驱动程序以不同的字节序编码UUID。使用以下选项卡比较不同MongoDB语言驱动程序将前面的UUID编码为Binary
子类型3的方式
00112233-4455-6677-8899-aabbccddeeff
33221100-5544-7766-8899-aabbccddeeff
77665544-3322-1100-ffee-ddccbbaa9988
为了标准化UUID字节序,我们创建了Binary
子类型4。尽管此子类型在MongoDB驱动程序中得到一致处理,但某些MongoDB部署仍包含子类型3的UUID值。
重要
在存储或检索子类型3的UUID时要小心。由一个MongoDB驱动程序存储的此类UUID值,当由不同的驱动程序检索时,可能具有不同的值。
指定UUID表示
为了确保您的PyMongo应用程序正确处理UUID,请使用UuidRepresentation
选项。此选项确定驱动程序如何将UUID对象编码为BSON,以及如何从BSON解码Binary
子类型3和4值。
您可以通过以下方式设置UUID表示选项
在构建
MongoClient
时传递uuidRepresentation
参数。PyMongo使用指定的UUID表示对所有使用此MongoClient
实例执行的操作进行编码。在MongoDB连接字符串中包含
uuidRepresentation
参数。PyMongo使用指定的UUID表示对所有使用此MongoClient
实例执行的操作进行编码。在调用
get_database()
方法时传递codec_options
参数。PyMongo使用指定的UUID表示对所有检索到的数据库执行的操作进行编码。在调用
get_collection()
方法时传递codec_options
参数。PyMongo 使用指定的 UUID 表示法执行所有检索集合的操作。
从以下选项卡中选择以查看如何指定前面的选项。有关可用的 UUID 表示法的更多信息,请参阅支持的UUID表示形式.
uuidRepresentation
参数接受在以下枚举中定义的值:UuidRepresentation。以下代码示例指定了 UUID 表示法的 STANDARD
from bson.binary import UuidRepresentation client = pymongo.MongoClient("mongodb://<hostname>:<port>", uuidRepresentation=UuidRepresentation.STANDARD)
uuidRepresentation
参数接受以下值
未指定
标准
pythonLegacy
javaLegacy
csharpLegacy
以下代码示例指定 UUID 表示法的 standard
uri = "mongodb://<hostname>:<port>/?uuidRepresentation=standard" client = MongoClient(uri)
当调用 get_database()
方法以指定 UUID 格式时,创建 CodecOptions
类的实例,并将 uuid_representation
参数传递给构造函数。以下示例显示了如何使用 CSHARP_LEGACY
UUID 格式获取数据库引用
from bson.codec_options import CodecOptions csharp_opts = CodecOptions(uuid_representation=UuidRepresentation.CSHARP_LEGACY) csharp_database = client.get_database("database_name", codec_options=csharp_opts)
提示
您还可以在调用 database.with_options()
方法时指定 codec_options
参数。有关此方法的更多信息,请参阅配置读写操作指南中的数据库和集合。
当调用 get_collection()
方法以指定 UUID 格式时,创建 CodecOptions
类的实例,并将 uuid_representation
参数传递给构造函数。以下示例显示了如何使用 CSHARP_LEGACY
UUID 格式获取集合引用
from bson.codec_options import CodecOptions csharp_opts = CodecOptions(uuid_representation=UuidRepresentation.CSHARP_LEGACY) csharp_collection = client.testdb.get_collection("collection_name", codec_options=csharp_opts)
提示
您还可以在调用 collection.with_options()
方法时指定 codec_options
参数。有关此方法的更多信息,请参阅配置读写操作指南中的数据库和集合。
支持的UUID表示形式
以下表格总结了PyMongo支持的UUID表示形式
UUID表示形式 | 将 UUID 编码为 | 将 Binary 子类型4解码为 | 将 Binary 子类型3解码为 |
---|---|---|---|
UNSPECIFIED (默认) | 引发 ValueError | Binary 子类型4 | Binary 子类型3 |
Binary 子类型4 | UUID | Binary 子类型3 | |
Binary 子类型3(标准字节序) | Binary 子类型4 | UUID | |
Binary 子类型3(Java遗产字节序) | Binary 子类型4 | UUID | |
Binary 子类型3(C#遗产字节序) | Binary 子类型4 | UUID |
以下部分更详细地描述了前面的UUID表示形式选项。
UNSPECIFIED
注意
UNSPECIFIED
是PyMongo中的默认UUID表示形式。
当使用UNSPECIFIED
表示形式时,PyMongo将BSON Binary
值解码为相同子类型的Binary
对象。要将Binary
对象转换为本地UUID
对象,请调用Binary.as_uuid()
方法并指定UUID表示形式格式。
如果您尝试在此表示形式下编码UUID
对象,PyMongo将引发ValueError
。为了避免这种情况,可以在UUID上调用如以下示例所示的Binary.from_uuid()
方法。
explicit_binary = Binary.from_uuid(uuid4(), UuidRepresentation.STANDARD)
以下代码示例显示了如何检索包含UNSPECIFIED
表示形式的UUID的文档,然后将该值转换为UUID
对象。为此,代码执行以下步骤
使用
CSHARP_LEGACY
UUID 表示法插入包含uuid
字段的文档。使用
UNSPECIFIED
表示法检索相同的文档。PyMongo 将uuid
字段的值解码为Binary
对象。调用
as_uuid()
方法将uuid
字段的值转换为类型为CSHARP_LEGACY
的UUID
对象。转换后,此值与 PyMongo 插入的原始 UUID 相同。
from bson.codec_options import CodecOptions, DEFAULT_CODEC_OPTIONS from bson.binary import Binary, UuidRepresentation from uuid import uuid4 # Using UuidRepresentation.CSHARP_LEGACY csharp_opts = CodecOptions(uuid_representation=UuidRepresentation.CSHARP_LEGACY) # Store a legacy C#-formatted UUID input_uuid = uuid4() collection = client.testdb.get_collection('test', codec_options=csharp_opts) collection.insert_one({'_id': 'foo', 'uuid': input_uuid}) # Using UuidRepresentation.UNSPECIFIED unspec_opts = CodecOptions(uuid_representation=UuidRepresentation.UNSPECIFIED) unspec_collection = client.testdb.get_collection('test', codec_options=unspec_opts) # UUID fields are decoded as Binary when UuidRepresentation.UNSPECIFIED is configured document = unspec_collection.find_one({'_id': 'foo'}) decoded_field = document['uuid'] assert isinstance(decoded_field, Binary) # Binary.as_uuid() can be used to convert the decoded value to a native UUID decoded_uuid = decoded_field.as_uuid(UuidRepresentation.CSHARP_LEGACY) assert decoded_uuid == input_uuid
STANDARD
当使用 STANDARD
UUID 表示法时,PyMongo 将本机 UUID
对象编码为子类型 4 的 Binary
对象。所有使用 STANDARD
表示法的 MongoDB 驱动程序以相同的方式处理这些对象,不更改字节顺序。
在所有新的应用程序中以及所有首次使用 MongoDB UUIDs 的应用程序中使用 STANDARD
UUID 表示法。
PYTHON_LEGACY
PYTHON_LEGACY
UUID 表示法对应于 PyMongo 旧版本(小于 v4.0)中使用的 UUID 的旧表示法。当使用 PYTHON_LEGACY
UUID 表示法时,PyMongo 将本机 UUID
对象编码为子类型 3 的 Binary
对象,保留与 UUID.bytes
属性相同的字节顺序。
如果您从 MongoDB 读取的 UUID 是使用 PYTHON_LEGACY
表示法插入的,请使用 PYTHON_LEGACY
UUID 表示法。以下两个条件都满足时,这将是正确的
UUID 是使用版本小于 v4.0 的 PyMongo 应用程序插入的。
插入 UUID 的应用程序未指定
STANDARD
UUID 表示法。
JAVA_LEGACY
JAVA_LEGACY
UUID 的表示形式对应于 MongoDB Java 驱动程序使用的 UUID 的旧表示形式。当使用 JAVA_LEGACY
UUID 表示形式时,PyMongo 将原生 UUID
对象编码为具有 Java 旧字节序的 Binary
子类型 3 对象。
如果您从 MongoDB 读取的 UUID 是使用 JAVA_LEGACY
表示形式插入的,请使用 JAVA_LEGACY
UUID 表示形式。以下两个条件都满足时,则为真
UUID 是使用 MongoDB Java 驱动程序的应用程序插入的。
应用程序未指定
STANDARD
UUID 表示形式。
CSHARP_LEGACY
CSHARP_LEGACY
UUID 的表示形式对应于 MongoDB .NET/C# 驱动程序使用的 UUID 的旧表示形式。当使用 CSHARP_LEGACY
UUID 表示形式时,PyMongo 将原生 UUID
对象编码为具有 C# 旧字节序的 Binary
子类型 3 对象。
如果您从 MongoDB 读取的 UUID 是使用 CSHARP_LEGACY
表示形式插入的,请使用 CSHARP_LEGACY
UUID 表示形式。以下两个条件都满足时,则为真
UUID 是使用 MongoDB .NET/C# 驱动程序的应用程序插入的。
应用程序未指定
STANDARD
UUID 表示形式。
故障排除
ValueError: 无法对本地uuid.UUID对象进行编码,因为UUID表示为uuidrepresentation.unspecified
此错误是由于尝试将本地UUID对象编码为二进制对象,而UUID表示为UNSPECIFIED,如下代码示例所示
unspecified_collection.insert_one({'_id': 'bar', 'uuid': uuid4()}) Traceback (most recent call last): ... ValueError: cannot encode native uuid.UUID with UuidRepresentation.UNSPECIFIED. UUIDs can be manually converted to bson.Binary instances using bson.Binary.from_uuid() or a different UuidRepresentation can be configured. See the documentation for UuidRepresentation for more information.
相反,您必须显式使用Binary.from_uuid()
方法将本地UUID转换为二进制对象,如下例所示
explicit_binary = Binary.from_uuid(uuid4(), UuidRepresentation.STANDARD) unspec_collection.insert_one({'_id': 'bar', 'uuid': explicit_binary})
API文档
要了解更多关于UUID和PyMongo的信息,请参阅以下API文档