• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

MongoDB数据类型

MongoDB 彭东稳 8年前 (2016-03-17) 21133次浏览 已收录 0个评论

MongoDB数据类型

MongoDB 的数据模式是一种灵活模式。关系型数据库要求你在插入数据之前必须先定义好一个表的模式结构,而MongoDB的集合则并不限制文档结构。这种灵活性让对象和数据库文档之间的映射变得很容易。即使数据记录之间有很大的变化,每个文档也可以很好的映射到各条不同的记录。当然在实际使用中,同一个集合中的文档往往都有一个比较类似的结构。

MongoDB的文档类似于JSON,在概念上和javascript中的对象神似。JSON是一种简单的表示数据的方式,包含6中数据类型。这带来很多好处:易于理解、易于解析、易于记忆。但另一方面,JSON的表现力也有限制,因为只有NULL、布尔、数字、字符串、数组和对象几种类型。

虽然这些类型的表现力以及足够强大,但是对于绝大多数应用来说还需要另外一些不可或缺的类型,尤其是与数据库打交道的哪些应用。例如,JSON没有日期类型,这会使得处理本来简单的日期问题变得非常繁琐。只有一种数字类型,没法区分浮点数和整数,也没有办法表示其他常用类型,如正则表达式或函数。所以MongoDB在保留JSON基本的键/值对特性的基础上,添加了其他一些数据类型。在不同的编程语言下这些类型的表示有些差异,下面列出了MongoDB通常支持的类型,同时说明了在Shell中这些类型是如何表示为文档的一部分的。

null – null用于表示空值或者不存在的字段

布尔布尔类型有两个值“true”和“false”,用于存储布尔值(真/假)。

64位浮点数 – shell中的数字都是这种类型,下面是一个浮点数

这个也是浮点数

字符串 存储数据常用的数据类型,在MongoDB中,UTF-8编码的字符串才是合法的。

对象ID对象ID时文档的12字节的唯一ID

日期UNIX时间格式来存储当前日期或时间,你可以指定自己的日期时间:创建Date对象,传入年月日信息,不存储时区。

正则表达式文档中可以包含正则表达式,采用javascript的正则表达式语法。

数组值的集合或者列表可以表示成数组。

内嵌文档文档可以包含别的文档,也可以作为值陷入到父文档中。

 

日期

javascript中,Date对象用做MongoDB的日期类型,创建一个新的Date对象时,通常会调用new Date()而不只是Date()。调用构造函数(也就是说不包括new)实际上会返回对日期的字符串表示,而不是真正的Date对象。这不是MongoDB的特性,而是javascript本身的特性。要是不小心忘了使用Date构造函数,最后就会导致日期和字符串混淆。字符串和日期不能相互匹配,所以这会给删除、更新、查询等很多操作带来问题。

数字

JavaScript中只有一种“数字”类型。因为MongoDB中有3种数字类型(32位整数、64位整数和64位浮点数),shell必须绕过JavaScript的限制。默认情况下,shell中的数字都被MongoDB当做是双精度数。这意味着如果你从数据库中获得的是一个32位整数,修改文档后,将文档存回数据库的时候,这个整数也被转换成了浮点数,即便保持这个整数原封不动也会这样的。所以明智的做法是尽量不要在shell下覆盖整个文档。

数组

数组是一组值,既可以表示为有序对象(列表,栈,队列等)也可以表示无序对象(集合),Shell中这样表示一个数组:{“things”[“pie”3.14]}。从中,我们可以看出数组可以包含不同数据类型的元素,实际上,常规键值对支持的所有值类型都可以放到数组中。数组中也可以嵌套数组。文档中的数组有个特性:MongoDB可以深入到数组内部进行搜索,如上例我们可以查询“things”数组中包含3.14这个值的所有文档。如果后期我们这种查询用得特别多,可以对“things”创建索引,以提高查询速度。

_idObjectId

MongoDB中存储的文档必须有一个“_id”键,这个键的值可以是任何类型的,默认是个ObjectId对象。在一个集合里面,每个文档都有唯一的“_id”值,来确保结合里面每个文档都能被唯一标识。如果有两个集合的话,两个结合可以都有一个值为123的“_id”键,但是每个集合里面只能有一个“_id”是123的文档。

ObjectId是“_id”的默认值类型,它涉及成轻量型的,不同机器都可以采用同样的机制去生成不同的主键。MongoDB没有采用自增长这种最常用的主键策略,是因为其天生面向分布式数据库,在大量主机间同步自增长的主键值费时,费力还容易出错,所以MongoDB从一开始就设计用来作为分布式数据库,处理多个节点是一个核心要求。后面会看到ObjectId类型在分片环境中要容易生成得多。

ObjectId采用12个字节的存储空间,每个字节两位十六进制数字,是一个24位的字符串。由于看起来很长,不少人会觉得难以处理。但关键是要知道这个长长的ObjectId是实际存储数据的两倍长。如果快速连续创建多个ObjectId,会发现每次只有最后几位数字有变化。另外,中间的几位数字也会变化(要是在创建的过程中停顿几秒钟)。这是ObjectId的创建方式导致的,12字节按照如下方式生成:

这样可以足可以保证这个值得唯一性。

刚才也说了,向集合中插入文档,如果文档中没有键“_id”,MongoDB会自动补入,但最佳实践是:客户端插入的文档带有这个键,并且保证其值是集合唯一的。这样做,首先能减少数据库端的开销,并且也体现了一种设计理念:能从数据库层转移到应用层的操作就转移出去,毕竟扩展应用层比扩展数据库层容易太多!这样做,还有一个好处就是,我们在插入文档后,可以讲文档的“_id”直接返回给客户端,如果我们通过MongoDB去生成这个值,我们insert后还需find一遍,才可以得到这个值。


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (1)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!