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生成通常是客户端驱动程序就可以做到,这样也减轻了数据库服务器的负担