MongoDB ObjectID 生成器 - 创建唯一的 BSON 标识符
在线免费生成符合MongoDB官方规范的ObjectID标识符,每个ID由12字节共24位十六进制字符组成的BSON数据构成,内部依次包含4字节时间戳、5字节随机值和3字节自增计数器。可一次批量生成1到100个互不重复的唯一标识符,全部计算在浏览器本地完成,适合数据库开发测试和调试演示使用。
MongoDB 对象ID生成器
文档
什么是 MongoDB ObjectID?
MongoDB ObjectID 是一个 12 字节的值,MongoDB 默认会将其分配给每个文档的 _id 字段。它表示为 24 个小写十六进制字符,例如 507f1f77bcf86cd799439011。此工具可直接在浏览器中一次生成 1 到 100 个有效的 ObjectID,无需连接数据库。
MongoDB ObjectID 的结构
ObjectID 由三个部分依次连接而成:
- 时间戳(4 字节)。 自 1970年1月1日(Unix 纪元)以来的秒数,以无符号大端序数值存储。它记录 ObjectID 的创建时间。四个字节可保存从 0 到 4,294,967,295 的值,因此该字段在 2106年2月7日 06:28:15 UTC 之后会回绕到 0。
- 随机值(5 字节)。 程序启动时随机选择一次的数值。此后该程序创建的每个 ObjectID 都会复用同一个随机值,因此不同计算机无需协调。
- 计数器(3 字节)。 从 0 到 16,777,215 之间的随机位置开始,每生成一个新的 ObjectID 就增加 1。如果超过 16,777,215,就回绕到 0。
将这些部分首尾相接后,形式如下:
1timestamp (8 hex chars) + random value (10 hex chars) + counter (6 hex chars) = 24 hex chars
2较早版本的 MongoDB 驱动程序使用机器标识符和进程 ID 构成中间部分,而不是使用随机数。当前的驱动程序,包括此工具背后的逻辑,则为每个进程使用一个随机的 5 字节值。
MongoDB ObjectID 的格式与公式
ObjectID 背后没有类似百分比或利息计算的算术公式。它是将三个数转换为十六进制文本后按顺序首尾连接而成的:
- 取当前时间自 Unix 纪元以来的秒数,并将其限制在 0 到 4,294,967,295 的范围内,使其适合存入四个字节。将其写成一个 8 位十六进制数。
- 取进程固定的随机值,即从 0 到 2^40 − 1 之间的数值。将其写成一个 10 位十六进制数。
- 取计数器的当前值,范围为 0 到 16,777,215。将其写成一个 6 位十六进制数,然后将计数器增加 1,供下一个 ID 使用。
- 按此顺序连接三个十六进制字符串,得到一个长度为 24 个字符的字符串。
计算示例
假设程序在 Unix 时间 1,700,000,000 秒时启动,即 UTC 时间 2023年11月14日 22:13:20。它选择随机值 3f2a91c8d4,并将计数器的起始值设为 12,345。
- 十六进制时间戳:
6553f100 - 十六进制随机值:
3f2a91c8d4 - 十六进制计数器:
003039
将这些部分连接起来,得到第一个 ObjectID:
6553f1003f2a91c8d4003039
如果程序在同一秒内生成第二个 ObjectID,时间戳和随机值保持不变,但计数器增加到 12,346(00303a):
6553f1003f2a91c8d400303a
读取 ObjectID 时也可以反向解析。给定 507f1f77bcf86cd799439011,其前 8 个字符 507f1f77 可解码为自纪元以来的 1,350,508,407 秒,即 UTC 时间 2012年10月17日 21:13:27。
MongoDB ObjectID 的常见用途
- 主键。 MongoDB 会自动将 ObjectID 放入文档的
_id字段,除非提供了其他值。 - 按创建时间查询。 由于其中嵌入了时间戳,程序无需单独的日期字段,就可以读取文档的大致创建时间。
- 按插入顺序排序。 按
_id对文档排序,大致相当于按创建时间排序,因为时间戳位于该值的开头。 - 测试数据和模拟数据。 开发人员使用生成的 ObjectID 构建示例文档或自动化测试,无需运行数据库。
MongoDB ObjectID 与 UUID
UUID(通用唯一标识符)是一个 16 字节的值,比 ObjectID 多四个字节。标准 UUID 通常整体具有随机性,因此不会透露创建时间,也不会按创建顺序排序。ObjectID 更短,并且大致按时间排序;这也是 MongoDB 默认使用它的原因之一,不过它不具备正确生成的 UUID 所具有的同等正式唯一性保证。
常见问题
MongoDB ObjectID 用于什么?
它是 MongoDB 放入文档 _id 字段的默认值,因此每个文档无需额外设置就能获得唯一键。
MongoDB ObjectID 能保证唯一吗? 从严格的形式化数学意义上说不能保证,但发生碰撞的可能性极低。两个 ObjectID 必须在同一秒内具有相同的随机值和相同的计数器位置才会碰撞,而这通常只会发生在同一个进程中。
可以从 ObjectID 中读取创建日期吗? 可以。前 8 个十六进制字符,即 4 个字节,保存自 Unix 纪元以来的秒数。将该数值转换为日期,即可得到大致的创建时间。
此生成器一次可以生成多少个 ObjectID? 每批可生成 1 到 100 个。一个批次中的所有 ID 共享同一个进程级随机值,并且每个 ID 的计数器都比前一个高一。
MongoDB ObjectID 可以在 MongoDB 之外使用吗? 可以。由于它们只是编码为十六进制文本的 12 字节值,因此也可以在其他系统中用作唯一 ID,不过数据库自身的 ID 方案可能更适合其需求。
此生成器连接到真实的 MongoDB 数据库吗? 不连接。它完全在浏览器中运行,不会从任何数据库读取数据,也不会向任何数据库写入数据。
参考文献
- "ObjectId." MongoDB 手册,https://www.mongodb.com/docs/manual/reference/method/ObjectId/.
- "ObjectId Specification." MongoDB BSON 规范,https://github.com/mongodb/specifications/blob/master/source/bson-objectid/objectid.md.
- "BSON Types." BSON 规范,https://bsonspec.org/spec.html.