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 的创建时间。
- 随机值(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 纪元以来的当前时间(以秒计),将其写成 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 大四个字节。版本 4 的 UUID 由随机数构成,因此不会暴露创建时间,也不按创建顺序排序。同一标准还定义了版本 7 的 UUID,它以毫秒为单位的 Unix 时间戳开头,并按时间排序。ObjectID 更短,大致按时间排序。RFC 9562 指出 UUID 旨在跨空间和时间保持唯一,但仍要求实现者权衡冲突的后果;对这两种格式而言,冲突在实践中都极不可能发生。
常见问题
MongoDB ObjectID 用于什么?
它是 MongoDB 放入文档 _id 字段的默认值,因此每个文档无需额外设置就能获得唯一键。
MongoDB ObjectID 能保证唯一吗? 从严格的形式化数学意义上说不能保证,但发生碰撞的可能性极低。两个 ObjectID 必须在同一秒内具有相同的随机值和相同的计数器位置才会碰撞,而这通常只会发生在同一个进程中。
可以从 ObjectID 中读取创建日期吗? 可以。前 8 个十六进制字符,即 4 个字节,保存自 Unix 纪元以来的秒数。将该数值转换为日期,即可得到大致的创建时间。
此生成器一次可以生成多少个 ObjectID? 每批可生成 1 到 100 个。一个批次中的所有 ID 共享同一个进程级随机值,并且每个 ID 的计数器都比前一个高一。
MongoDB ObjectID 可以在 MongoDB 之外使用吗? 可以。由于它们只是编码为十六进制文本的 12 字节值,因此也可以在其他系统中用作唯一 ID,不过数据库自身的 ID 方案可能更适合其需求。
此生成器连接到真实的 MongoDB 数据库吗? 不连接。它完全在浏览器中运行,不会从任何数据库读取数据,也不会向任何数据库写入数据。
参考文献
- MongoDB。BSON Types: ObjectId。BSON 类型 — ObjectId 为 12 字节(4 字节时间戳、5 字节随机值、3 字节计数器),默认填充
_id,并大致按创建时间排序。 - MongoDB。ObjectID specification。BSON ObjectID 规范 — 无符号大端序时间戳、每个进程生成一次的随机值、从随机值开始并在 16,777,215 之后重置为 0 的计数器,以及较早的机器 ID 和进程 ID 字段。
- IETF。RFC 9562: Universally Unique IDentifiers (UUIDs)。RFC 9562 — UUID 为 16 个八位组(128 位);版本 4 为随机型,版本 7 按时间排序。