您的位置:首页 > 数据库 > Mongodb

MongoDB数据类型

2012-05-30 16:51 246 查看


数据类型

基本数据类型

.monbodb里面的文档可以理解为json
类似的对象。json格式简单,只支持6种数据类型。很多时候这是好事,容易被理解,解析和记忆。但是,json的表达能力是有限的。因为只支持null、boolean、numeric、string、array
和object 这几种类型。

 

尽管这些类型的通常场合足够表达了。但是还是存在其它很多的数据类型,尤其是数据库。例如json
没有日期类型,对日期的处理要烦恼一些。它有数字类型,但没办法区分浮点和整形。更不用说严格区分32位和64位了。正则表达式和函数类型也没办法表现。

 

monbodb采取了json
的键值对的同时,还支持很多额外的数据类型。虽然不同的语言支持的类型有所不同,但还是有很多共同类型的:

 

null

Null代表空值和不存在的值

{"x" : null}

 

boolean

只有 true 和false

{"x" : true}

 

32-bit integer

Shell分不出来,一概认为是64位的。会自动转换

64-bit integer

Again, the shell cannot represent these.The shell will display them using a specialembedded  document; see the section
“Numbers” on page 18
for details.

64-bit floating point number

Shell里面所有数字都认为是这个类型:

{"x" : 3.14}

 

这个也是

{"x" : 3}

 

string

任意 UTF-8 字符:

  

symbol

{"x" : "foobar"}

Shell不支持,会转化为string

object id

唯一的12位ID. 

{"x" : ObjectId()}

 

date

 

实际保存为从世纪开始到现在的毫秒数,不支持时区:

{"x" : new Date()}

 

regular expression

采用js 的正则表达式语法

{"x" : /foobar/i}

 

code

可以包含js代码

{"x" : function() { /* ... */ }}

 

binary data

二进制. shell不能处理

maximum value

BSON 包含一个特殊类型来表示可能的最大值。Shell不支持.

minimum  value

BSON 包含一个特殊类型来表示可能的最小值。Shell不支持.

undefined

Undefined 也可以在document里面用(js表示undefined和null
是不一样的):

{"x" : undefined}

 

array

列表:

{"x" : ["a", "b","c"]}

 

embedded document

嵌套的文档:

{"x" : {"foo" : "bar"}}

Numbers

JS 有一个number
的类型。因为mongodb 有3个数字类型(4字节整数、8字节整数、8字节浮点)在shell
里面的数字都会默认当作浮点数。这意味着如果你从数据库取出一个4字节整数,然后存进去,即使没有改变它,也会变成了8字节浮点数。因此通常不要把整个document覆盖到mongodb里面去比较好。

另外的一个问题是,一个8字节的整数是不能用8字节的浮点数来表示的。因此如果你保存一个8字节整数然后在shell里面查看它,shell
将会显示为一个嵌套的document来精确的描述它,例如如果我们在document
里面讲myInteger 这个key
的值保存为一个64位的整数,3,然后在shell
里面查看,将会这样显示:

> doc = db.nums.findOne()

{

"_id" : ObjectId("4c0beecfd096a2580fe6fa08"),"myInteger" : {

"floatApprox" : 3

}

}

 

这个数字在数据库里面不会改变(除非你用shell重新保存了一次,这样会转化为浮点);这个嵌套的文档只是用shell显示一个8字节的整数的浮点近似值。这个嵌套文档只有一个key。

如果你插入一个不能用浮点来精确表示的8字节整数:shell会加上2个key,to
和bottom,分别代表高位和低位的32位值。例如9223372036854775807会如下显示

> db.nums.findOne()

{

"_id" : ObjectId("4c0beecfd096a2580fe6fa09"),"myInteger" : {

"floatApprox" : 9223372036854776000, "top" :2147483647,

"bottom" : 4294967295

}

}

The "floatApprox"
embedded  documents are special and can be manipulated as num- bers as well as documents:

> doc.myInteger + 1

4

> doc.myInteger.floatApprox

3

 

所有4字节整数可以用8字节浮点数表示,因此正常显示。.

 

Dates

js里面,Date 对象用来表示MongoDB
的日期类型。创建日期对象要用 new Date(),而不是用Date(),后者只是返回一个字符串,并不是一个Date的对象。这不是MonboDB
的问题,而是js就是这样的。如果你不注意就会弄混字符串和日期类型。在删除更新查询的时候造成问题。

shell 里面用本地区域设置来显示日期。但在数据库里面只是记录从纪元开始到现在所过去的毫秒数。所以并没有区域设置保存进去。(当然你可以用另外的key
来保存)

 

Arrays

数组是一组值可以进行有序处理,类似列表,堆栈,队列,或者无序处理,类似集合。.

 

{"things" : ["pie", 3.14]}

 

这里看到数组里面的成员类型是允许不一样的。其实可以是任意的类型,包括嵌套的数组都可以。.

 

.MongoDB 的好处是,它理解数组里面的结构并知道怎么进入内部执行操作。这让我们可以进行查询操作和索引操作,上例,monboDB可以查询所有文档找出things包括3.14,也可以为things建立索引以提高查询速度。

 

MongoDB还允许数组内部元素的原子更新,例如把pie改为pi.  

Embedded Documents

嵌套文档就是将一个key 的值表示为另外一个文档。这样可以让document
看起来比一个平面的结构更自然些.

例如,如果我们有一个文档表示一个人并保存它的地址,就可以嵌套表示为:

{

"name" : "John Doe", "address" : {

"street" : "123 Park Street", "city" :"Anytown",

"state" :"NY"

}

}

 

跟数组一样,mongoDB也理解嵌套文档的结构,可以进行内部的查询和更新.

 

晚点我们会深入讨论schema设计模式。但从这个简单例子,我们也可以了解嵌套文档改变了我们处理数据的方式。传统数据库中这两个信息将会存放在两个表的两条记录中但mongoDB可以用一个文档来表示,如果合理使用嵌套文档可以提供更加自然的信息表示(通常也更有效率).

 

从负面看这种方式不是那么的正规,造成了数据冗余,假设一个地址两个人使用那么关系数据库里面可以用一条记录表示,通过join来关联,但mongoDB只能分别存放,分别更新。

 

_id and
ObjectIds

所有文档必须具有_id 键。值类型可以任意的,但通常是ObjectID。一个集合里面,文档的_id是唯一的。但如果是两个集合,他们之间的文档ID就可以重复。

ObjectIds

.ObjectID是 _id的缺省类型。轻量设计,可以在不同的服务器很容易产生一个唯一值。这就是为什么mongodb
用它而不用传统的id例如自增ID
的原因。自增ID 很难在不同的服务器同步。因为mongodb一开始就设计为一个分布式的数据库,处理很多节点是重要的考虑事项。

 

ObjectID 用12字节存储,可以表示为24个16进制数字形成的字符串:每个字节2个数字。因此看起来很长,让很多人觉得困惑。其实是存储长度的2倍。

 

如果很快的产生大量的ObjectID,会发现每次只有2个数字改变,通常中部的2个数字改变。这是ObjectID创建的方式。12个字节的规划为下图

 

0    
1      2      3      4      5      6      7      8      9      10      11

Timestamp                
Machine             PID           Increment

 

前面四个字节是自纪元开始秒数,这就提供了几个有用的属性。

 

• The timestamp, when combined  withthe next five bytes (which will be described in a moment), provides uniqueness  at the granularity of a second.

• 因为时间放前面,因此ObjectID
大体上是按照插入的顺序排列的。虽然并不绝对保证,This is not a strong guarantee but does have some nice properties, such as making
ObjectIdsefficient to index.

• 因此,大多数驱动提供一个方法,来从ObjectID获取创建时间的信息。

有人可能会担心是否需要几台服务器同步时间,这是不必要的担心。

接下来3位跟机器相关,通常是取主机名的hash值。这就避免了多台服务器的id
冲突.

接下来的两位跟进程相关,可以保证同一个机器的不同进程产生相同ID

 

前面9位保证多个服务器不同进程在不同的秒产生不同的ID,最后3个字节是一秒当中的流水,最大可以保证产生 2563
(16,777,216)个唯一id。

 

自动产生ID

前面说过,如果插入的时候 _id 没有值,那么服务器会产生一个。这个可以由服务器处理,但一般是client
端处理比较好。因为:

• A虽然ObjectID的设计是很轻量的,容易产生,但还是有一些开销。在客户端产生ID
实际上也反映了monboDb的哲学。尽量让客户端多做一些事情。虽然Monbodb是可扩展的系统,但扩展应用程序总是比扩展db来的有效率。

• 有利客户端的api
设计。假设在服务器端产生id,那么一个插入的api
还需要另外从服务器查询一次才能得到插入文档的Id。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息