02 入门

MongoDB基本概念
☑ 文档:MongoDB中数据的基本单元
☑ 聚合:没有模式的表
☑ 数据库:每个数据库都有自己的集合和权限,每个MongoDB可以包含多个独立的数据库实例
☑ JavaScript shell:对于管理MongoDB实例和操作数据库作用非常大
☑ _id:每个文档的特殊键,在文档所处的集合中是唯一的

1 文档:多个键及其关联的值有序地放置在一起便是文档

特点
☑ 文档的键/值对是有序的
☑ 文档的值可以是多种数据类型
☑ 文档的键可以使任何UTF-8字符组成的字符串,一些特别的要求如下:

1
2
3
☑ 键不能包含有\0(空字符),这个字符用来表示键的结尾
☑ .和$有特别的意义,只有在特定环境下才能使用
☑ 以下划线"_"开头的键是保留的,但并不严格要求

2 集合:一组文档,如同表

无模式:一个集合中的文档可以是各式各样的。

要是没必要对各种文档划分模式,那么为什么还要使用多个集合呢?

1
2
3
4
☑ 开发和管理:如果不适用集合,需要确保查询返回需要的文档种类或者对返回的数据进行筛选
☑ 速度:拆分成多个集合可以提高查询的速度
☑ 磁盘:放在一个集合会增加磁盘寻道消耗
☑ 索引:索引是按照集合来定义的,按照文档类型放入不同的集合中可以使索引更加高效

子集合:使用”.”字符分开爱的按命名空间划分的子集合
☑ 用途:很多 MongoDB 工具中都包含子集合。
☑ GridFS:一种存储大文件的协议,使用自己和来存储文件的元数据。
☑ MongoDB 的 web 控制台:通过自己和的方式将数据组织在 DBTOP 部分。
☑ 数据驱动程序:绝大多数驱动程序都提供语法糖,为访问指定集合的自己提供方便。

3 数据库:多个集合组成数据库

特点
☑ 一个MongoDB实例承载多个数据库
☑ 多个数据库之间完全独立,有各自独立的权限控制,存放在不同的文件中

命名
数据库名最终会变成文件系统里的文件名

☑ 不能使用空字符串
☑ 不得含有''(空格) . $ / \\0(空字符)
☑ 应全部小写
☑ 最多64字节

保留的数据库名
☑ admin: 从权限的角度看,在合适“root”数据库,被添加进该数据库的用户会自动继承所有数据库权限;一些重要服务需要在该服务器运行
☑ local:该数据库永远你不会被赋值,可以用来存储本地单台服务器的任意集合
☑ config:在内部使用,用于保存分片的相关信息
命名空间:把数据库的名字放在集合名前面,得到的就是集合的完全限定名
☑ 限制:<121字节

4 启动MongoDB

1
2
3
4
$ sudo mkdir -p /data/db
$ sudo chmod enter /data/db
$ sudo chgrp enter /data/db
$ ./mongod ----没有参数的情况下默认数据目录为/data/db,端口为27017

5 MongoDB shell

5.1 运行shell

☑ 是什么:包含一个功能完备的JS解释器,可以执行管理操作、检查运行实例,亦可做其他尝试。
☑ 注意:启动时会自动连接 MongoDB 服务器

1
2
$ mongod    # 先启动服务
$ mongo # 打开与MongpDB实例进行交互的shell

5.2 MongoDB客户端

1
2
3
>db    ----该全局变量指向当前连接的数据库
>use foobar ----选择要使用的数据库
>db.baz ----访问数据库中的baz集合

5.3 shell中的基本操作

1. 创建:insert()

1
2
3
4
5
6
7
8
9
10
11
>post = {"title":"My Blog Post",
... "content":"Here's my blob post.",
..."date":new Date()
}
>db.blog.insert(post) # 为db.blog集合插入一个文档
>db.blob.find() # 查看db.blog集合中的所有文档
{
"title":"My Blog Post",
"content":"Here's my blob post.",
"date":new Date()
}

2. 读取

find():查看集合中的所有文档
findOne():只查看一个文档

1
2
3
4
5
6
>db.blob.findOne()    ----查看db.blog集合中的所有文档
{
"title":"My Blog Post",
"content":"Here's my blob post.",
"date":"Sat Dec 12 2009 11:13:21 GMT-0500 (EST)"
}

3. 更新:update()

1
2
3
4
5
6
7
8
9
10
>post.comments = []
>db.blob.update({title:"My Blog Post"}, post);
>db.blob.find()
{
"id":ObjectId("4b23c3ca7525f35f94b60a2d"),
"title":"My Blog Post",
"content":"Here's my blob post.",
"date":"Sat Dec 12 2009 11:13:21 GMT-0500 (EST)"
"comments":[]
}

4. 删除:remove()

1
>db.blob.remove({title:"My Blog Post"}) # 删除指定文档

5.4 使用shell的窍门

http://api.mongodb.org/js

使用帮助文档

1
2
3
4
>help # 最全最详细
>db.help() # 数据库级别的帮助信息
>sb.foo.help() # 集合级别的帮助信息
>db.foo.update # 查看某个函数的实现机理

蹩脚的集合名

☑ 问题一:JS只有在db中找不到指定的属性时,才会将其作为集合返回
☑ 问题二:JS错误解析包含无效JS字符的集合

解决:getCollection()

1
2
3
4
5
6
>db.version
function(){
return this.serverBuildInfo().version;
}
>db.getCollection("version");
test.version
1
>db.getCollection("foo-bax"); # 获得foo-bax集合

访问子集合:在JS中x.y <==> x['y']

1
2
3
4
var collections = ["posts", "comments", "authors"];
for(i in collections){
doStuff(db.blog[collections[i]]);
}

6 数据类型

MongoDB在保留JSON基本的键/值对特性的基础上,添加了其它一些数据类型。

6.1 基本数据类型

数据类型 说明 shell支持 举例
null 空值或者不存在的字段 {“x”:null}
布尔 ‘true’或者’false’ {“x”:true}
32位整数 会被自动转换为64位浮点数
64位整数 是使用一个特殊的内嵌文档来显示之
64位浮点数 shell中所有数字类型都使这种类型 {“x”:3.14}
字符串 UTF-8字符串可以表示为字符串类型的数据 {“x”:”foobar”}
符号 shell将数据库中的符号类型转换为字符串
对象id 文档的12字节的唯一ID {“x”:ObjectId()}
日期 从标准纪年开始的毫秒数,不存储时区 {“x”:new
正则表达式 采用JS的正则表达式语法 {“x”:/foobar/i}
代码 JS代码 {“x”:function(){}}
二进制数据 任意字节的串
最大值 BSON包含的一种类型,表示可能的最大值
最小值 BSON包含的一种类型,表示可能的最小值
未定义 undefined {“x”:undefined}
数组 值得集合或列表 {“x”:[“a”, “b”, “c”]}
内嵌文档 可以包含别的文档,也可以作为值嵌入到父文档中 {“x”:{“foo”:”bar”}}

6.2 数字

注意

☑ JS有1种“数字”类型,MongoDB 有3种,shell 比许绕过 JS 的限制,默认情况下 shell 中的数字都会被当作双精度数。尽量不要再 shell 下覆盖文档
32 位整数都能用64位浮点数精确表示
有些 64 位整数不能精确表示为 64 位浮点数,因此在 shell 中会显示为一个内嵌文档,表示可能不准确:

1
2
3
4
5
6
7
>doc = db.nums.findOne()
{
"id":ObjectId("4c0beecfd096a2580fe6fa08"),
"myInteger":{
"floatApprox":3 # 插入的64位整数可以用64为浮点数精确表示的情况
}
}
1
2
3
4
5
6
7
8
9
>doc = db.nums.findOne()
{
"id":ObjectId("4c0beecfd096a2580fe6fa08"),
"myInteger":{
"floatApprox":3, # 插入的64位整数不可以用64为浮点数精确表示的情况,可以作为值和文档来操作
"top":2147483647, # 高32位
"bottom":4294967295 # 低32位
}
}

6.3 日期:在JS中,Date对象用做MongoDB的日期类型

☑ new Date():返回日期对象
☑ Date():返回日期字符串

注意: shell中的日期显示时使用本地时区设置,在数据中是以从标准纪元开始的毫秒数的形式存在,没有与之相关的时区信息

6.4 数组

特点:MongoDB能够“理解”其结构,并指导如何深入数组内部对其内容进行操作

6.5 内嵌文档

☑ 说明:就是把整个MongoDB文档作为另一个文档中键的一个值

1
2
3
4
5
6
7
8
9
10
11
{
"name":"Join Doe",
"address":{
"street":"123 Park Street",
"address":{
"street":"123 Park Street",
"city":"Anytown",
"state":"NY"
}
}
}

☑ 优点:更加自然高效
☑ 缺点:在成数据重复,反规范化,维护麻烦

6.6 _id 和 ObjectId

☑ _id:MongoDB 中存储的文档必需有一个”_id”键,可以是任意类型,默认是 ObjectId 对象;每个集合中的文档的”_id”值必须是唯一的。

1. ObjectId

大小 12 个字节,每个字节存储一个十六进制数字,可以看成一串 24 位的字符串。

0 1 2 3 4 5 6 7 8 9 10 11
时间戳(保证秒一级的唯一性) 机器(通常是机器主机名的散列值) PID 计数器

2. 自动生成_id

情况一:插入文档时没有指定”_id”键,系统会自动创建一个

情况二:在客户端由驱动程序生成(推荐)
☑ 扩展应用层比扩展数据库层容易得多,能从服务器端转移到驱动程序来做的事,就尽量转移
☑ 在客户端生成 ObjectId ,驱动程序能够提供更加丰富的 API