深入理解mongo中的数据类型,了解Mongo的Id生成策略

本文深入探讨了MongoDB中的数据类型,包括布尔型、null、数值、字符串、日期、正则表达式、数组、内嵌document、ObjectId等。特别强调了ObjectId的12字节结构,由时间戳、机器标识、进程ID和计数器组成,确保其唯一性。此外,还介绍了如何查看字段类型及数据类型的转换方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mongoDB的document与javaScript中对象类似,document类似JSON, 但是 JSON本身有一些局限性, 比如JSON数据类型相对较少, 没有日期类型;只有一种数字类型,无法区分浮点和整数,无法表示通用类型,比如正则表达式或者函数

MongoDB中,document在保留JSON key-value的基础上,添加了一些数据类型 ,

下面就展开说一下,mongo中的基本数据类型,
  • 布尔型 : 有两个值 true、false
  • null : 表示 空值 或者不存在的字段
  • 数值 : shell 默认使用64位浮点, 整数可以用NumberInt类(4字节带符号)、NumberLong(8字节带符号)
  • 字符串 : UTF-8字符串都可表示为字符串类型的数据
  • 日期 : 存储新纪元以来毫秒数
  • 正则表达式 : 和JavaScript类似, 语法相同,用作限定条件
  • 数组 : 就是一个数组
  • 内嵌document
  • ObjectId : 12字节的ID,document的唯一标识

还有其他不太常见的

  • 二进制数据 : 不能直接在shell中使用,保存非UTF-8的字符
  • 代码 : 比如 {x:function(){}}

一些具体细节可以查看 “官方文档” ,

接下来说一下,如何查看一个filed的类型

查看文档中某一个field的类型,用typeof

>  typeof db.employee.findOne({}).salary
  number
  • 字符串
    保存UTF-8格式的字符,和js使用字符串语法一样,虽然单个字符串不一定有长度限制,但是document最多保存16M, 所以可能会发生字段被截断的问题,简单提一下

    {a:'123'}
    

    字符串转日期、日期转字符串 (shell)

       var aDate = new Date (db.test.findOne({_id:2}).a) // 把a转为日期格式
       var a = db.test.findOne({_id:2}).aDate.valueOf()
    
  • Number
    对于这个类型,mongo和js处理不一样,需注意一下, 默认是浮点型,如果想修改为整形,用NumberInt、想修改为long用 NumberLong

  • Date
    对比js, shell中定义一个 时间类型

     > var a = new Date()
    > a
    ISODate("2019-09-20T09:18:17.009Z")
    > var b = new Timestamp()
    > b
    Timestamp(0, 0)
    > db.test.insertOne({data:a,timestamp:b})
    {
    	"acknowledged" : true,
    	"insertedId" : ObjectId("5d8499992159547228d8d26f")
    }
    > db.test.find()
    { "_id" : ObjectId("5d8499992159547228d8d26f"), "data" : ISODate("2019-09-20T09:18:17.009Z"), "timestamp" : Timestamp(1568971161, 1) }
    

    当然,mongo本身还和一些其他语言结合使用,用提供给其他语言的插件, 在这些语言中,如果需要时间格式数据,需要用对应语言的时间戳格式

  • 数组
    基本特性和JavaScript类似, 比如 可以保存不同类型的数据,甚至可以嵌套一个数组

    {thing :["pie",3.14, [1,2]]}
    

    document中数组有个特性 , mongoDB可以理解数组的结构,可以深入数组内部进行操作,这样可以使用数组内容对数组进行查询和构建索引,mongoDB可以修改数组中的某一内容

提一下, ObjectId
  • mongoDB中Id
    我们知道,在没有显示指定Id的,mongodb会为我们提供一个id.
    ObjectId是12个字节的存储空间 , 24个十六进制的数字组成的字符串 (每个字节可以保存两个十六进制的数字)

    // 一个二进制的数字,比如 15就是下边的四位
     1111  
    // 一个字节是8位
    0111 1111
    // 所以, 如下objectId ,比如
     5d844f632159547228d8d26c   
     // 全翻译成二进制篇幅太长,所以只翻译 5d 如下, 其他的类似
     0101   1101
    
  • 基本格式
    实际上,这12 个字节的Id ,格式如下
    在这里插入图片描述
    比如上边代码中提到的Id, 用空格分隔如下

    // 时间戳  机器  PID  计数器 
    5d844f63 215954 7228 d8d26c
    

    时间戳 :
    不一定要采用服务器时间同步,没有必要,只要做到不停增加 (每秒一次) , 比如上边的时间戳,转为时间,如下

    5d844f63  
    // 先转为十进制 时间戳 
    1568952163
    //  十进制时间戳,转为北京时间
    2019-09-20 12:02:43
    

    上边的时间戳,转化为具体时间之后,可以发现,是按秒进行修改,换句话说,每一秒产生Id不同。

    如果,想看时间转换,可以使用 “在线进制转换器”、 ”在线时间戳转换“ ,这里就不多介绍。

    机器 :
    保证不同机器产生不同的ID,通常是机器主机名三劣质

    PID :
    保证,即使同一机器,不同mongo进程产生不同的Id

    计数器 :
    保证,同一机器,同一秒内, 同一进程,如果插入多条,id也会不同。 至于有没有可能不够,这里简单分析一下 , 另外 看很多博主说最多产生2563个,猜测是单纯看得“mongodb权威指南” , ,此书中这样描述 ,如下图
    在这里插入图片描述
    这应该是错误的,实际上我们知道 计数器是三个字节 (每个字节是八位),如下

    0111 1111 1111 1111 1111 1111 
    

    24个字节,最多有多少个数呢, 实际上是
    2 24 2^{24} 224
    一共是 16777216 (十进制)种,所以书本应该是打印错误,是
    25 6 3 256^{3} 2563
    上边是一点题外话,总之,这是一个非常大的数字了,几乎不可能在一秒内一个进程可以插入这么多数据,目前处理器还没有这么强大,所以,基本上,id是不会重复的

  • 优点
    这样设计而不是采用单纯累加器,是因为mongo生来就是要支持并发多机器的,要求不同机器也不能产生相同ID

    采用ObjectId的Id生成策略,实际上不会出现重复ID,无论是多少台并发处理器,所以id生成通常是客户端驱动程序就可以做到,这样也减轻了数据库服务器的负担

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值