MongoDB:18-MongoDB-ObjectId

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: MongoDB:18-MongoDB-ObjectId


MongoDB中我们经常会接触到一个自动生成的字段:”_id”,类型为ObjectId。


ObjectId构成


  1. 之前我们使用MySQL等关系型数据库时,主键都是设置成自增的。
  2. 但在分布式环境下,这种方法就不可行了,会产生冲突。
  3. 为此,MongoDB采用了一个称之为ObjectId的类型来做主键。
  4. ObjectId是一个12字节的 BSON类型字符串。按照字节顺序,依次代表:
  5. 4字节:UNIX时间戳
  6. 3字节:机器识别码
  7. 2字节:表示生成此_id的进程
  8. 3字节:由一个随机数开始的计数器生成的值

  1. 如:
  1. 4df2dcec2cdcd20936a8b817

  1. TimeStamp
  2. 4位是一个unix的时间戳,是一个int类别,我们将上面中的objectid的前4位进行提取“4df2dcec”,
  3. 然后再将他们安装十六进制 专为十进制:“1307761900”,这个数字就是一个时间戳,为了让效果更佳明显,
  4. 我们将这个时间戳转换成我们习惯的时间格式(精确到秒)
  1. $ date -d '1970-01-01 UTC 1307761900  sec'  -u
  2. 20110611日 星期六 03:11:40UTC

  1. 4个字节其实隐藏了文档创建的时间,并且时间戳处在于字符的最前面,
  2. 这就意味着ObjectId大致会按照插入进行排序,这对于某些方面起到很大作用,作为索引提高搜索效率等等。
  3. 使用时间戳还有一个好处是,某些客户端驱动可以通过ObjectId解析出该记录是何时插入的,
  4. 这也解答了我们平时快速连续创 建多个Objectid时,会发现前几位数字很少发现变化的现实,
  5. 因为使用的是当前时间,很多用户担心要对服务器进行时间同步,其实这个时间戳的真实值并 不重要,只要其总不停增加就好。
  6. Machine
  7. 接下来的三个字节,就是 2cdcd2 ,这三个字节是所在主机的唯一标识符,一般是机器主机名的散列值,
  8. 这样就确保了不同主机生成不同的机器hash值,确保在分布式中不造成冲突,
  9. 这也就是在同一台机器生成的objectid中间的字符串都是一模一样的原因。
  10. pid
  11. 上面的Machine是为了确保在不同机器产生的objectid不冲突,
  12. 而pid就是为了在同一台机器不同的mongodb进程产生了objectid不冲突,接下来的0936两位就是产生objectid的进程标识符。
  13. increment
  14. 前面的九个字节是保证了一秒内不同机器不同进程生成objectid不冲突,这后面的三个字节a8b817,
  15. 是一个自动增加的计数器,用来确保在同一秒内产生的objectid也不会发现冲突,允许2563次方等于16777216条记录的唯一性。



  1. MongoDB中存储的文档必须有一个"_id"键。这个键的值可以是任何类型的,默认是个ObjectId对象。
  2. 在一个集合里面,每个文档都有唯一的"_id"值,来确保集合里面每个文档都能被唯一标识。
  3. MongoDB采用ObjectId,而不是其他比较常规的做法(比如自动增加的主键)的主要原因,
  4. 因为在多个 服务器上同步自动增加主键值既费力还费时。



  1. 补充:1个字节占多少个16进制位
  2. 1个字节是8位,最多表示0256
  3. 而一位16最多只表示到16,即F表示16,要表示到256,就还需要第二位,
  4. 所以1个字节占216进制位
  5. 一个16进制位占0.5个字节



创建新的ObjectId


  1. 使用以下代码生成新的ObjectId
  2. >newObjectId = ObjectId()
  3. 上面的语句返回以下唯一生成的id:
  4. ObjectId("5349b4ddd2781d08c09890f3")
  5. 你也可以使用生成的id来取代MongoDB自动生成的ObjectId
  6. >myObjectId = ObjectId("5349b4ddd2781d08c09890f4")


创建文档的时间戳


  1. 由于 ObjectId 中存储了 4 个字节的时间戳,所以你不需要为你的文档保存时间戳字段,
  2. 你可以通过 getTimestamp 函数来获取文档的创建时间:
  3. >ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()
  4. 以上代码将返回 ISO 格式的文档创建时间:
  5. ISODate("2014-04-12T21:49:17Z")


根据时间构造ObjectId


  1. // 使用Date的字符串构造方法生成日期
  2. // 然后使用Date对象的getTime获取毫秒数,再除以1000得到标准时间戳
  3. > a = newDate("2012-12-12 00:00:00").getTime()/1000
  4. 1355241600
  5. // 获取时间戳的标准十六进制表示
  6. > a = a.toString(16)
  7. 50c75880
  8. // 在后面填补16个0
  9. > a = a + newArray(17).join("0")
  10. 50c758800000000000000000
  11. // 使用24个字符串构造ObjectId
  12. > b = newObjectId(a)
  13. ObjectId("50c758800000000000000000")
  14. // 获取时间以验证
  15. > b.getTimestamp()
  16. ISODate("2012-12-11T16:00:00Z")
  17. 上述过程中 newArray(17).join(“0″)目的是生成160拼接的字符串。
  18. 这里使用了点小技巧。
  19. newArray(17)构造了一个17个元素的数组,但是数组里面没有元素,
  20. join(atr)方法的作用是连接数组元素并且以其参数分割。17个元素正好有16个间隔,
  21. 所以最终拼接起来的字符串为16个。


ObjectId转换为字符串


  1. 在某些情况下,您可能需要将ObjectId转换为字符串格式。你可以使用下面的代码:
  2. >newObjectId().str
  3. 以上代码将返回Guid格式的字符串::
  4. 5349b4ddd2781d08c09890f3


根据ObjectId按照插入时间排序


  1. MongoDB默认在ObjectId上建立索引,是按照插入时间排序的。
  2. 我们可以使用此索引进行查询和排序。
  3. // 按序插入三个文档
  4. > db.col.insert({"num":1})
  5. > db.col.insert({"num":2})
  6. > db.col.insert({"num":3})
  7. > db.col.find().pretty()
  8. { "_id" : ObjectId("53102fb4bf1044ed8b0ba36c"), "num" : 1 }
  9. { "_id" : ObjectId("53102fb9bf1044ed8b0ba36d"), "num" : 2 }
  10. { "_id" : ObjectId("53102fbabf1044ed8b0ba36e"), "num" : 3 }
  11. // 按照_id升序,即按照插入时间升序
  12. > db.col.find().sort({"_id":1}).pretty()
  13. { "_id" : ObjectId("53102fb4bf1044ed8b0ba36c"), "num" : 1 }
  14. { "_id" : ObjectId("53102fb9bf1044ed8b0ba36d"), "num" : 2 }
  15. { "_id" : ObjectId("53102fbabf1044ed8b0ba36e"), "num" : 3 }
  16. // 按照_id降序,即按照插入时间降序
  17. > db.col.find().sort({"_id":-1}).pretty()
  18. { "_id" : ObjectId("53102fbabf1044ed8b0ba36e"), "num" : 3 }
  19. { "_id" : ObjectId("53102fb9bf1044ed8b0ba36d"), "num" : 2 }
  20. { "_id" : ObjectId("53102fb4bf1044ed8b0ba36c"), "num" : 1 }
  21. // 抽取num = 2的ObjectId用来过滤
  22. > num2 = ObjectId("53102fb9bf1044ed8b0ba36d")
  23. ObjectId("53102fb9bf1044ed8b0ba36d")
  24. // 找出插入时间在num2之后的数据
  25. > db.col.find({ "_id":{$gt:num2}}).pretty()
  26. { "_id" : ObjectId("53102fbabf1044ed8b0ba36e"), "num" : 3 }


参考来源: http://blog.csdn.net/permike/article/details/51800948

参考来源: http://blog.csdn.net/xiamizy/article/details/41521025


相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
3天前
|
监控 NoSQL MongoDB
【MongoDB】MongoDB 索引
【4月更文挑战第1天】【MongoDB】MongoDB 索引
|
NoSQL 索引 MongoDB
MongoDB ObjectId详解及使用
MongoDB中我们经常会接触到一个自动生成的字段:”_id”,类型为ObjectId。 本文详解ObjectId的构成和使用。 ObjectId构成 之前我们使用MySQL等关系型数据库时,主键都是设置成自增的。
1168 0
|
9月前
|
NoSQL 前端开发 MongoDB
MongoDB应用
初始化路由模板 数据库和前端页面交互 编写注册的后台接口 先连接数据库 和前台进行数据交互 文章的后台接口 先查询所有的文章内容 发文章 一些验证方法 邮箱验证 用户名随机生成
41 0
|
9月前
|
存储 NoSQL 关系型数据库
什么时候选择MongoDB
什么时候选择MongoDB
67 2
|
10月前
|
存储 SQL NoSQL
mongoDB(二)
mongoDB
71 0
|
10月前
|
JSON NoSQL MongoDB
初学mongoDB(一)
初学mongoDB
49 0
|
存储 缓存 NoSQL
MongoDB 使用介绍
MongoDB 是由 C++ 语言编写的,是一个基于分布式文件存储的非关系型开源数据库系统。其优势在于可以存放海量数据,具备强大的查询功能,是一个独立的面向集合文档形式的。
307 0
MongoDB 使用介绍
|
存储 分布式计算 NoSQL
MongoDb的主要特点
MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易
224 0