MongoDB是一款强大、灵活、易于扩展的、由C++编写的聚合型、文档型、NoSQL数据库,支持二级索引、范围查询、排序、聚合、地理空间索引等功能。
MongoDB是面向文档的数据库,不是关系型数据库,不采用关系模型是为了更好的扩展性。与关系型数据库相比,有以下特点:
- 没有“一行数据”的概念,取而代之的是“一条文档”
- 不再有预定义模式,文档的键和值不再是固定的类型和大小,可以随意扩展。
- 易于扩展,随着数据的增长,横向扩展(增加机器)变得更加方便,MongoDB能够自动处理跨集群的数据和负载,自动重新分配文档、自动将用户请求路由至正确的机器上。
- 功能丰富,支持索引、聚合、文件存储、以及特殊集合,如会过期的数据:日志、会话等。
- 性能更强,4.0版本前不支持事务,但提供了诸多原子操作:文档的保存、修改、删除。
文档与集合
文档是MongoDB中数据的基本单元,类似于关系型数据库管理系统中的行,但灵活性更高。例如:
{"name":"xiaoming","age":20}
集合是一组文档,可以看做是一个拥有动态模式的表。因此,MongoDB中的文档没有预定义模,一个集合中可以保存多个完全不同的文档,例如:
1 | 1 {"name":"xiaoming", "age":20} |
备注:集合命名时,不能有空字符串、不能包含\0、不能包含$、不能以system.开头
数据库
多个集合组成一个数据库、一个MongoDB实例包含多个数据库,每个数据库拥有独立的权限,在磁盘上,不同的数据库放置在不同的文件夹中,一般的,一个应用程序使用一个数据库。
有三个数据库是默认保留的:admin(root库)、local(用于副本集模式)、config(用于分片模式)
数据类型
MongoDB的文档与JavaScript中对象相近,类似于JSON,MongoDB支持JSON包含的6种数据类型:null、布尔型、数值、字符串、数组、对象,MongoDB还添加了其他一些数据类型:日期、正则表达式、数组、内嵌文档、对象id、二进制数据、JavaScript代码。
下面只介绍:日期、数组、内嵌文档、对象id。
日期
对应JAVA、JS中的Date类,存入数据库的是Date对象,不是日期字符串。数据库中存储的日期为新纪元以来的毫秒数,并未存储时区,Date对象与毫秒之间的转换,由MongoDB负责,客户端不需要关心。
数组
与JAVA数组不同的是,数组可以包含不同类型的元素,数组可以嵌套数组。
1 | {"things":["apple", 3.1415926]} |
内嵌文档
文档可以作为键的值,这样的文档就是内嵌文档。类似于JSON嵌套。
1 | { |
objectId
MongoDB存储的文档必需有一个”_id“键,这个键可以是任意类型,默认是个ObjectId对象。objectId作为文档的唯一标识符。如果插入文档时,没有设置objectId,MongoDB客户端驱动会自动创建一个。
object_id大小为12字节,是一个由24个十六进制数字组成的字符串。
时间戳:占用前4个字节,从标准纪元开始的时间戳,单位为秒,
机器标识位:占用3个字节,是所在主机名的唯一标识,通常是机器名的hash值。
PID:产生 objectId的进程的ID
计数器: 前9个字节保证了同一秒钟不同机器不同进程的ObjectId是唯一的,最后三个字节用来确保同一秒同机器同进程的objectId的唯一性。所以每个进程同一秒最多允许产生
$$
(2^8)^3=16777216
$$
个不同的objectId。对于服务器来说,1600W个足够用了。
从objectId的设计可以看出,MongoDB的设计初衷就是用作分布式数据库,能够在副本集、分片环境下生成全局唯一id。