Skip to content

MongoDB - ObjectId

MongoDB 集合中的每个文档都需要一个唯一的 _id 字段作为其主键。如果您不提供,MongoDB 会在插入文档时自动为 _id 字段生成一个唯一的 ObjectId。

一个 ObjectId 是一个 12 字节的 BSON 类型,经过精心设计,以确保在不同机器和不同时间具有高度的唯一性。它由以下部分组成:

  • 一个 4 字节时间戳值,表示 ObjectId 的创建时间,以 Unix 纪元以来的秒数衡量。
  • 一个 5 字节随机值(这取代了以前的机器 + 进程 ID,以实现更好的分布)。
  • 一个 3 字节递增计数器,初始化为随机值。

这种结构为您的文档提供了默认的、可排序的、全局唯一的标识符。

您可以在 mongosh 或您的应用程序驱动程序中按需生成新的 ObjectId。

// 在 mongosh 中
> const newId = new ObjectId()
> newId
ObjectId("615cc1b3f72d5c4b1e9b1e2a")

由于创建时间嵌入在 ObjectId 中,您可以提取它而无需单独的 createdAt 字段(尽管显式时间戳通常更清晰)。使用 getTimestamp() 方法:

> const myId = new ObjectId("615cc1b3f72d5c4b1e9b1e2a")
> myId.getTimestamp()
ISODate("2021-10-05T19:33:07.000Z")

此功能使 ObjectId 可以自然地按创建时间排序。

通常,您需要将 ObjectId 的值用作字符串,例如在 REST API URL 中、在日志文件中,或作为发送到 Web 客户端的 JSON 对象中的键。

使用 .toString() 或 .toHexString() 方法获取 24 字符的十六进制字符串表示。遗留的 .str 属性已弃用。

> const myId = new ObjectId()
ObjectId("615cc204f72d5c4b1e9b1e2b")
> myId.toString()
'615cc204f72d5c4b1e9b1e2b'
> myId.toHexString()
'615cc204f72d5c4b1e9b1e2b'
  • 不变性: _id 字段是不可变的。文档插入后,您不能更新其 _id。如果您需要更改它,必须创建一个带有新 _id 的新文档,并删除旧文档。
  • 自定义 _id: 您可以为 _id 提供自己的值,只要它在集合中是唯一的。这在使用自然主键时很常见,例如用户的电子邮件或产品 SKU。但是,这些自定义键不保证具有与 ObjectId 相同的有用排序属性。
  • 客户端生成: ObjectId 可以在文档甚至发送到数据库之前由客户端驱动程序生成。这允许您在插入文档之前就知道文档的 ID,从而可以简化应用程序逻辑。