Contents
文档
多个键/值对有序放置在一起便是文档。文档类似于关系数据库中的行,但比行要复杂很多。
- 文档中键值对是有序的
- 文档中的值可以是字符串,也可以是其它数据类型。除了少数情况,键可以使用任意UTF-8字符
- 键不能含有
\0
,这个字副用来表示键的结尾 .
,$
有特别的意义,通常是保留的- 以
_
开头的键是保留的 - mongodb区分类型同时也区分大小写
- mongodb不能有重复的键
{“one”:”hello”,”one”:”world”} 是非法的
下面几组文档是不同的:
1 | {"foo":3} |
1 | {"foo":3} |
1 | {"one":"hello","foo":3} |
集合
集合就是一组文档,类似于关系数据库的表
无模式
集合是没有模式的,一个集合里面的文档可以是各式各样的,例如:
1 | {"one":"hello"} |
上面文档不光值类型不同,键也完全不同。但是为了检索,索引更加有效,快捷,有必要创建一个模式把相关文档规整到一起。
命名
- 不能是空字符串
""
- 不能含有
\0
- 不能以”system.”开头,这是系统集合保留的前缀
- 不能含有保留字符”$”
子集合
组织集合的一种惯例是使用”.”字符分开的按命名空间划分的子集合。例如blog.posts,blog.authors,这样可以使组织关系更好,也就是说blog这个集合(这里根本不需要存在)及其子集合没有任何关系。
数据库
多个集合可以组成数据库,一个mongodb实例可以承载多个数据库,它们之间可视为完全独立的。
命名
- 不能是空字符串
""
- 不能含有
(空格)、.、$、/、\和
\0
- 应全部小写
- 最多64字节
数据库名会变成文件系统文件,所以命名会有这些限制
一些数据库是系统保留的,如下
admin
‘root’数据库,如果把用户加入这个数据库,这个用户将继承所有数据库权限,一些特定的服务器端命令也只能从这个数据库运行,如列出所有数据库或关闭数据库。local
这个数据库永远不会被复制,可用来存储限于本地单台服务器的任意集合config
当mongo用于分片设置时,在内部使用,用于保存分片信息。
数据库名放在集合名前,得到的就是集合的完全限定名,即命名空间。如在cms数据库中使用blog.posts集合,这个集合的命名空间就是cms.blog.posts。命名空间长度不应超过121字节,实际应用中应小于100字节。
MongoDB shell
运行mongo
会自动连接mongodb服务器。shell是一个完备的JavaScript解释其,可运行任何JavaScript程序。
启动shell会自动连接到test数据库,并将数据库的连接赋值给全局变量db
选择使用的数据库
1 | use foobar |
查看当前数据库
1 | db |
可以通过db变量访问其中的集合。db.baz将返回当前数据库的baz集合。
基本操作
创建
insert函数可以添加一个文档到集合中。1
2
3
4
5post = { "title" : "my blog",
"content" : "my blog post",
"date": new Date()
}
db.blog.insert(post)读取
find会返回集合中所有文档,findOne返回一个文档。
1
2db.blog.find()
db.blog.findOne()两个函数可以接受一些限定条件。使用find自动显示最多20个匹配的文档。
更新
update接受两个参数,更新文档的限定条件和新的文档。给先前的文章增加评论内容
1
2post.comments = []
db.blog.update({title:"my blog"}, post)删除
remove用来永久性删除文档,没有参数的话将会删除一个集合内的所有文档,也可以指定限定条件。
1
db.blog.remove({title:"my blog"})
技巧
查看帮助文档
help
db.help() 查看数据库级别的帮助
db.foo.help() 查看集合相关帮助
db.foo.update 可以查看该函数javascript源代码
通过http://api.mongodb.org/js 查看javascript函数api文档。
蹩脚的集合名
通过db.集合名 的方式访问集合一般是没有问题的。但是如果集合名恰好是数据库类的属性就有问题了。只有在找不到指定属性时才会将其作为集合返回,,所以
db.version
将得到属性,而不是集合。
这种情况下,可以使用getCollection函数访问集合1
db.getCollection("version")
如果集合名中含有无效javascript字符,这个函数也是很有用的。
1
db.getCollection("foo-bar")
如果不这样,
-
会被javascript当成减号,
javascript中,x.y和x[‘y’]是等价的,所以可以通过变量访问子集合。
可以通过下面方式对blog子集合访问1
2
3
4var collections = ["posts","comments","authors"]
for (i in collections){
doStuff(db.blog[collections[i]]);
}
数据类型
基本数据类型
null
表示空值或不存在的字段
布尔
有两个值’true’和’false’
32位整数
shell中这个类型不可用。javascript仅支持64位浮点数,所以32位整数会被自动转换。
64位整数
shell中也不支持这个类型,而会使用一个特殊内嵌文档来显示64位整数。
64位浮点数
shell中的数字都是这种类型
字符串
utf-8字符串可表示为字符串类型的数据
符号
shell不支持这种类型。shell将数据库中的符号类型转换成字符串。
对象id
对象id是文档的12字节的唯一id
日期
日期类型存储的是从标准纪元开始的毫秒数,不存储时区。
正则表达式
文档中可以包含正则表达式。采用javascript的正则表达式。
代码
文档中还可以包含javascript代码
二进制数据
二进制数据可以由任意字节的串组成。shell中无法使用。
最大值
BSON包括一个特殊类型,表示可能的最大值。shell中没有这个类型
最小值
BSON包括一个特殊类型,表示可能的最小值。shell中没有这个类型
未定义
文档中也可以使用未定义类型(javascript中null和undefined是不同的类型)
数组
值的集合或列表可以表示成数组
1
{"x":["a","b","c"]}
内嵌文档
文档可以包含别的文档也可以作为值嵌入到父文档中
1
{"x":{"foo":"bar"}}
注意
数字
javascript只有一种数字类型,mongodb有三种,默认情况下,shell中的数字都会被当做64位双精度浮点数。32位整数都能用64位浮点数表示,64位整数用64位浮点数表示有精度问题。
日期
创建新的Date对象,通常会调用new Date()而不是Date()。调用构造函数(不带new)实际返回对日期的字符串表示,而不是真正的Date对象。这不是mongodb特性,而是javascript的。日期不存储时区信息,可以把时区信息作为其他键的值存储。
数组
mongodb可以使用原子更新修改数组中的内容
内嵌文档
内嵌文档使信息表示更加自然,通常也更高效。但是是反规范化的,会有很多重复内容。
_id和ObjectId
mongodb每个文档必须有一个”_id”键,在每个集合中这个键是唯一的,不同集合中的键可以相同。
ObjectId
_id的默认类型。有12个字节。前四个字节是时间戳,和随后5个字节保证秒级别的唯一性,也保证ObjectId大致按插入顺序排列,同时也隐含了文档创建时间,可以提取出来。接着3个字节是主机唯一标示符,确保不同主机ObjectId不同。接下来两个字节是产生ObjectId的进程标识符,保证并发的多个进程产生ObjectId的唯一,最后3个字节是自动增加的计数器,确保相同进程同一秒产生的ObjectId的唯一性。同一秒最多拥有256的3次方个不同ObjectId
自动生成_id
插入文档,系统会自动加入_id。但是这样会增加服务器端的开销,能从服务器转移到客户端驱动程序,就应该转移。在客户端生成,驱动程序能够提供更加丰富的API。所以通常在客户端由驱动程序来创建_id