MongoDB入门下
1.使用shell的技巧
shell内置的帮助:
使用db.help()可以查看数据库级别的命令帮助,集合的相关帮助可以通过db.blog.help()
输入的时候不要输入括号,这样就可以显示该函数的javascript源代码:
使用db.集合名 的方式来访问集合一般不会有问题,但如果集合名恰好是数据库类的一个属性,这样会有问题,例如:
要访问version这个集合,使用db.version是不行的,因为db.version是个数据库函数.
当javascript只有在db中找不到指定的属性时,才会将其作为集合返回.当有属性与目标集合同名时,可以使用
getCollection函数,如:db.getCollection("version")
要查看名称中含有无效的javascript字符的集合,如:db.blog-refactor是个有效的集合名,但在javascript中就变成了
变量相减.通过db.getCollection("blog-refactor")可以得到blog-refactor集合.
在javascript中,x.y和x['y']是等价的.
var collections={"posts","comments","authors"};
for(i in collections)
{
doStuff(db.blog[collections[i]])
}
而不是写成这样:
doStuff(db.blog.posts)
doStuff(db.blog.comments)
doStuff(db.blog.authors)
2.数据类型
基本的数据类型
MongoDB的文档类似于JSON.在概念上与javascript中的对象相似.
MongoDB在保留JSON基本的键值对特性的基础上,添加了其他一些数据类型.
1.null
表示空值或者不存在的字段
{"x":null}
2.布尔值
true或false
{"x":false}
3.32位整数
shell中这个类型不适用,因为javascript只支持64位浮点数,所以32位整数会被自动转换
4.64位整数
shell中这个类型不适用,shell会使用一个特殊的内嵌文档来显示64位整数
5.64位浮点数
shell中的数字都是这种类型,下面都是浮点数
{"x":3.14}
{"x":3}
6.字符串
utf-8字符串都可表示为字符串类型的数据
{"x":"Refactor"}
7.符号
shell中这个类型不适用.shell将数据库里的符号类型转换成字符串
8.对象id
对象id是文档的12字节的唯一ID
{"x":ObjectId()}
9.日期
日期类型存储的是从标准纪元开始的毫秒数.不存储时区
{"x":new Date()}
10.正则表达式
文档中可以包含正则表达式,采用javascript语法
{"x":/refactor/i}
11.代码
文档中可以包含javascript代码
{"x":function(){....}}
12.二进制数据
二进制数据由任意字节的串组成,shell中不能用
13.最大值
BSON包含的特殊类型,表示可能的最大值,shell中不能用
14.最小值
BSON包含的特殊类型,表示可能的最小值,shell中不能用
15.未定义
文档中可以使用未定义类型
{"x":undefined}
16.数组
值的集合或列表可以表示成数组
{"x":["a","b","c"]}
17.内嵌文档
文档中可以包含别的文档,也可以作为值嵌入到父文档中
{"x":{"hello":"world"}}
数字类型
javascript中只有一个"数字"类型.MongoDB中有3种数字类型(32位整数,64位整数,64位浮点数),
shell必须绕过javascript的限制.默认情况下,shell中的数字都被MongoDB当成双精度数.这就意味着
如果你从数据库中获得的是一个32位整数,修改文档后,将文档存回到数据库的时候,这个整数就被转换成了
浮点数,即便是保持这个整数不修改,也会转换为浮点数.所以不应该子啊shell下覆盖整个文档.
数字只能表示为双精度数(64位浮点数)的另外一个问题是:有些64位整数并不能表示为64为浮点数,所以要存入
一个64位整数,在shell中查看,它会表示为一个内嵌文档,表示可能不准确.
日期类型
在javascript中,Date对象用作MongoDB的日期类型,创建一个新的Date对象,通常会调用new Date(),而不是 Date()
调用构造函数(不包括new)实际会返回对日期的字符串表示,而不是真正的Date对象,这是javaScript本身的特性.
shell中的日期显示时使用本地时区设置.但是,日期在数据中是从标准纪元开始的毫秒数的形式存储的,没有与之相关的时区信息
数组类型
数组是一组值,既可以作为有序对象(如:列表,栈或队列)来操作,也可以作为无序对象(如:集合)操作.
如:{"things":["pie",3.14]}
诉诸数组可以包含不同数据类型的元素(这个例子中是一个字符串和一个浮点数),实际上,常规键值对支持的值都可以
作为数组的元素,甚至是嵌套的数组
MongoDB可以查询所有"things"数组中还有3.14的文档,要是经常使用这个查询,可以对"things"创建索引,来提高性能
MongoDB可以使用原子更新修改数组中的内容,比如深入数组内部将pie改为pi.
内嵌文档类型
内嵌文档就是把整个MongoDB文档作为另一个文档中键的一个值.这样数据可以组织的更自然,不用非得存成扁平结构.
如:应一个文档来表示一个人,同时还要保存他的地址,可以将地址内嵌到文档中
peopleAddress=
{
"name":"Refactor",
"address":
{
"street":"wuzhong",
"city":"suzhou"
}
}
同数组一样,MongoDB能够理解内嵌文档的结构,并能深入其中 构建索引,执行查询或更新.
内嵌文档可以改变处理数据的方式,在关系型数据库中,之前的文档一般会拆分成两个表("people"和"address")
中的两个行.在MongoDB中,可以将地址文档直接嵌入到人员文档中.这样也有坏处,因为MongoDB会存储很多
的重复数据,如果在关系型数据库中"address"在一个独立的表中,要修改地址中的拼写错误.当我们对"address"表
进行修改后,那么每一个使用这个地址的人的信息都会得到更新.但在MongoDB中,则需要在每个人的文档中修改拼写错误
_id和ObjectId
MongoDB中存储的文档必须有一个"_id"键.这个键的值可以是任何类型,默认是ObjectId对象.
在一个集合里面,每个文档都有唯一的"_id"值,来确保集合里面每个文档都能唯一的标识.如果有
两个集合的话,两个集合可以都有一个值为123的"_id"键,但是每个集合里面只能有一个"_id"是123的文档
ObjectId是"_id"的默认类型,ObjectId可以确保分布式数据的唯一性
如果在插入文档的时候没有"_id"键,系统会自动帮你创建一个.可以由MongoDB服务器来做这件事情,
但通常会在客户端驱动程序完成,理由如下:
1.虽然ObjectId设计成轻量型的,易于生成的,但毕竟的生成的时候还是会产生开销.在客户端生成体现了
MongoDB的设计理念:能从服务端转移到驱动程序来做的就尽量转移.这种理念的原因是:扩展应用层比
扩展数据库层容易的多,将事务交由客户端处理,就减轻了数据库扩展的负担.
2.在客户端生成ObjectId,驱动程序能够提供更丰富的API.如驱动程序可以有自己的insert方法,可以返回生成
的ObjectId,也可以直接将其插入文档.如果驱动程序允许服务器生成ObjectId,那么将需要单独的查询,以确定
插入的文档中的"_id"值.