Mongodb中的ObjectId

使用mongodb时 , 当集合中的文档没有_id字段时,会为文档自动生成一个ObjectId类型的_id。日常查询过程中,也能看到_id是ObjectId里带有一段字符串, 这个字符串代表什么意义,和其他类型的ID有什么相同或不同。本文研究mongodb官方文档,并通过实践来解释ObjectID这个数据类型。

ObjectId定义

ObjectId是一种小型的,几乎是唯一的,易于产生和排序的数据结构。长度是12个字节,由3部分组成

  • 4个字节的时间戳,表明objectId的创建时间,以秒为单位的unix时间
  • 5个字节的随机字符串,在运行机器上的进程中是唯一的
  • 3个字节的增长计数器,初始值是一个随机数

其中时间戳和增长计数器与其他BSON类型不同,是按照高位优先排序。

如果使用数字类型来创建ObjectID, ObjectID中的时间戳,会被数字值来替代。

//使用数字类型定义3个ObjectID
db.inventory.insertMany([{
    part: 'AB307',
    _id: ObjectId(1)
},{
    part: 'AB307',
    _id: ObjectId(2)
},{
    part: 'AB307',
    _id: ObjectId(3)
}])

// 产生的id中,数字类型替代了4个字节的时间戳
{
	"acknowledged" : true,
	"insertedId" : ObjectId("000000013e53cb5bc48f4e54")
}
{
	"acknowledged" : true,
	"insertedId" : ObjectId("000000023e53cb5bc48f4e55")
}
{
	"acknowledged" : true,
	"insertedId" : ObjectId("000000033e53cb5bc48f4e56")
}

上面代码的运行结果中可以看到,4个字节长度的00000001,00000002,00000003,替代了时间错。而后面3个字节长度的增长计数器,8f4e54,8f4e55,8f4e56在每一条新纪录插入时,都会增长。而中间3e53cb5bc4这个长度为5个字节的字符串,是由运行机器进程中随机产生的字符串。

时间戳+随机字符串+自增长字符串,保证了objectId的唯一性。

文档中的ObjectId

Mongodb的每一个文档都需要有唯一的_id字段作为主键。如果没有_id字段,mongodb自动添加一个ObjectId作为_id字段。这对于设置{upsert:true}的更新语句插入数据同样适用。

使用ObjectId作为_id字段的好处

  • 在mongosh中,通过ObjectId.getTimestamp()方法,获取文档创建时间
//运行代码
ObjectId("655ef22e69185fac9ce3ce92").getTimestamp()
//获取创建时间
ISODate("2023-11-23T14:33:18.000+08:00")
  • 按照_id排序,等价于按照文档创建时间排序

ObjectId的单调性

ObjectId虽然按照时间来产生,并带有随机数保证其唯一性。但objectId并不是单调的,受到两个因素影响

  • 产生objectId仅仅以秒为单位,记录下来unix时间。当同一秒钟产生多个objectId时,并不能保证每一个objectid的排列顺序。
  • 通过client产生的ObjectId, 其时间错可能与服务器时间不一致

相关推荐

  1. MongodbObjectId

    2023-12-08 08:48:05       54 阅读
  2. MongoDB ObjectId 详解

    2023-12-08 08:48:05       31 阅读
  3. MongoDB 事务

    2023-12-08 08:48:05       50 阅读
  4. MongoDB物化视图

    2023-12-08 08:48:05       58 阅读
  5. MongoDB 锁分析

    2023-12-08 08:48:05       33 阅读
  6. mongodb字符串排序

    2023-12-08 08:48:05       39 阅读
  7. Mongodb查询投射$elemMatch

    2023-12-08 08:48:05       52 阅读
  8. MongoDB在业务应用

    2023-12-08 08:48:05       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-08 08:48:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-08 08:48:05       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-08 08:48:05       82 阅读
  4. Python语言-面向对象

    2023-12-08 08:48:05       91 阅读

热门阅读

  1. 看图学源码之 CopyOnWriteArraySet源码分析

    2023-12-08 08:48:05       47 阅读
  2. ZooKeeper学习一

    2023-12-08 08:48:05       46 阅读
  3. iSoftBook、Jira、GitLab、TAPT研发管理平台的比较

    2023-12-08 08:48:05       71 阅读
  4. Caddy服务器快速上手

    2023-12-08 08:48:05       57 阅读
  5. 【Angular开发】Angular:2023年最佳实践

    2023-12-08 08:48:05       57 阅读
  6. 用c#实现记事本的功能

    2023-12-08 08:48:05       46 阅读
  7. KVM迁移

    2023-12-08 08:48:05       40 阅读
  8. vue3在table里使用elementUI的form表单验证

    2023-12-08 08:48:05       51 阅读
  9. Boost:asio单io_service,多线程run

    2023-12-08 08:48:05       39 阅读
  10. C++设计模式学习之一(共计13种)

    2023-12-08 08:48:05       44 阅读
  11. LISP~~~~~

    2023-12-08 08:48:05       51 阅读