精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-05-03
数据类型 基本数据类型 .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 special embedded 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 with the 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 ObjectIds efficient 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。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-04-11
很多时候是好事也是坏事 经常出错
|
|
返回顶楼 | |
浏览 4192 次