MongoDB
是一个高性能,开源,无模式的文档型数据库,是当前
NoSQL
数据库产品中最热门的一种。它在许多场景下可用于替代传统的关系型数据库或键/值存储方式。
官方网址:
http://www.mongodb.org/
NoSQL,全称是”Not Only Sql”,指的是
非关系型的数据库
。这类数据库主要有这些特点:非关系型的、分布式的、开源的、水平可扩展的。
NoSQL 特点
1、它可以处理超大量的数据
2、它运行在便宜的 PC 服务器集群上
3、它击碎了性能瓶颈
通过 NoSQL 架构可以省去将 Web 或 Java 应用和数据转换成 SQL 格式的时间,执行速度变得更快。
4、它没有过多的操作
5、它的支持者源于社区
什么是MongoDB?
MongoDB 是一个
介于关系数据库和非关系数据库之间
的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似 json 的 bjson 格式,因此可以存储比较复杂的数据类型。 MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它是一个
面向集合的,模式自由的文档型
数据库。
1、
面向集合
(Collenction-Orented)
意思是数据被分组存储在数据集中, 被称为一个集合( Collenction)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库( RDBMS)里的表( table), 不同的是它不需要定义任何模式( schema)。
2、
模式自由
(schema-free)
意味着对于存储在 MongoDB 数据库中的文件,我们不需要知道它的任何结构定义。提了这么多次”无模式”或”模式自由”,它到是个什么概念呢?例如,下面两个记录可以存在于同一个集合里面:
{“welcome” : “Beijing”}
{“age” : 25}
3、
文档型
意思是我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档. 我们把这个数据格式称作 “ BSON” 即 “ Binary Serialized dOcument
Notation.”
特点:
面向集合存储,易于存储对象类型的数据
模式自由
支持动态查询
支持完全索引,包含内部对象
支持查询
支持复制和故障恢复
使用高效的二进制数据存储,包括大型对象(如视频等)
自动处理碎片,以支持云计算层次的扩展性
支持 Python, PHP, Ruby, Java, C, C#, Javascript, Perl 及 C++语言的驱动程序,社区中也提供了对 Erlang 及.NET 等平台的驱动程序
文件存储格式为 BSON(一种 JSON 的扩展)
可通过网络访问
功能:
面向集合的存储
:适合存储对象及 JSON 形式的数据
动态查询
: MongoDB 支持丰富的查询表达式。查询指令使用 JSON 形式的标记,可轻易查询文档中内嵌的对象及数组
完整的索引支持
:包括文档内嵌对象及数组。 MongoDB 的查询优化器会分析查询表达式,并生成一个高效的查询计划
查询监视
: MongoDB 包含一系列监视工具用于分析数据库操作的性能
复制及自动故障转移
: MongoDB 数据库支持服务器之间的数据复制,支持主-从模式及
服务器之间的相互复制
。复制的主要目标是提供冗余及自动故障转移
高效的传统存储方式
:支持二进制数据及大型对象(如照片或图片)
自动分片以支持云级别的伸缩性
:自动分片功能支持水平的数据库集群,可动态添加额外的机器
适用场合
网站数据
: MongoDB 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性
缓存
:由于性能很高, MongoDB 也适合作为信息基础设施的缓存层。在系统重启之后,由 MongoDB 搭建的持久化缓存层可以避免下层的数据源过载
大尺寸,低价值的数据
:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储
高伸缩性的场景
: MongoDB 非常适合由数十或数百台服务器组成的数据库。 MongoDB的路线图中已经包含对 MapReduce 引擎的内置支持
用于对象及 JSON 数据的存储
: MongoDB 的 BSON 数据格式非常适合文档化格式的存储及查询
MongoDB的安装
Windows 平台的安装
步骤一: 下载 MongoDB
url 下载地址: http://downloads.mongodb.org/win32/mongodb-win32-i386-1.8.1.zip
步骤二: 设置 MongoDB 程序存放目录
将其解压到 c:\,再重命名为 mongo,路径为 c:\mongo
步骤三: 设置数据文件存放目录
在 c:盘建一个 db 文件夹,路径 c:\db
步骤四: 启动 MongoDB 服务
进入 cmd 提示符控制台, c:\mongo\bin\mongod.exe –dbpath=c:\db
C:\mongo\bin>C:\mongo\bin\mongod –dbpath=c:\db
Sun Apr 10 22:34:09 [initandlisten] MongoDB starting : pid=5192 port=27017 dbpath=d:\data\db 32-bit
** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
** see http://blog.mongodb.org/post/137788967/32-bit-limitations
** with –dur, the limit is lower
……
Sun Apr 10 22:34:09 [initandlisten] waiting for connections on port 27017
Sun Apr 10 22:34:09 [websvr] web admin interface listening on port 28017
MongoDB 服务端的默认监听端口是 27017
步骤五: 将MongoDB 作为 Windows 服务随机启动
先创建 C:\mongo\logs\mongodb.log 文件,用于存储 MongoDB 的日志文件, 再安装系统服务。
C:\mongo\bin>C:\mongo\bin\mongod –dbpath=c:\ db –logpath=c:\mongo\logs\mongodb.log –install all output going to: c:\mongo\logs\mongodb.log
Creating service MongoDB.
Service creation successful.
Service can be started from the command line via ‘net start “MongoDB”‘.
C:\mongo\bin>net start mongodb
Mongo DB 服务已经启动成功。
C:\mongo\bin>
步骤六: 客户端连接验证
新打开一个 CMD 输入: c:\mongo\bin\mongo,如果出现下面提示,那么您就可以开始MongoDB 之旅了
C:\mongo\bin>c:\mongo\bin\mongo
MongoDB shell version: 1.8.1
connecting to: test
>
步骤七: 查看 MongoDB 日志
查看 C:\mongo\logs\mongodb.log 文件,即可对 MongoDB 的运行情况进行查看或排错了,这样就完成了 Windows 平台的 MongoDB 安装。
2.2 Linux 平台的安装
步骤一: 下载 MongoDB
下载安装包: curl -O http://fastdl.mongodb.org/linux/mongodb-linux-i686-1.8.1.tgz
步骤二: 设置 MongoDB 程序存放目录
将其解压到/Apps,再重命名为 mongo,路径为/Apps/mongo
步骤三: 设置数据文件存放目录
建立/data/db 的目录, mkdir –p /data/db
步骤四: 启动 MongoDB 服务
/Apps/mongo/bin/mongod –dbpath=/data/db
[root@localhost ~]# /Apps/mongo/bin/mongod –dbpath=/data/db
Sun Apr 8 22:41:06 [initandlisten] MongoDB starting : pid=13701 port=27017 dbpath=/data/db 32-bit
** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
** see http://blog.mongodb.org/post/137788967/32-bit-limitations
** with –dur, the limit is lower
……
Sun Apr 8 22:41:06 [initandlisten] waiting for connections on port 27017
Sun Apr 8 22:41:06 [websvr] web admin interface listening on port 28017
MongoDB 服务端的默认连接端口是 27017
步骤五: 将MongoDB 作为 Linux 服务随机启动
先创建/Apps/mongo/logs/mongodb.log 文件,用于存储 MongoDB 的日志文件
vi /etc/rc.local, 使用 vi 编辑器打开配置文件,并在其中加入下面一行代码
/Apps/mongo/bin/mongod –dbpath=/data/db –logpath=/Apps/mongo/logs/mongodb.log
步骤六: 客户端连接验证
新打开一个 Session 输入: /Apps/mongo/bin/mongo,如果出现下面提示,那么您就可以开始 MongoDB 之旅了
[root@localhost ~]# /Apps/mongo/bin/mongo
MongoDB shell version: 1.8.1
connecting to: test
>
步骤七: 查看 MongoDB 日志
查看/Apps/mongo/logs/mongodb.log 文件,即可对 MongoDB 的运行状况进行查看或分析了
[root@localhost logs]# ll
总计 0
-rw-r–r– 1 root root 0 04-08 20:15 mongodb.log
[root@localhost logs]#
以上的几个步骤就 OK 了!! 这样一个简单的 MongoDB 数据库就可以畅通无阻地运行起
来了。
MongoDB 中一系列物理文件(数据文件,日志文件等)的集合或与之对应的逻辑结构(集合,文档等)被称为数据库,简单的说,就是数据库是由一系列与磁盘有关系的物理文件的组成。
MongoDB 的逻辑结构是一种层次结构。主要由:
文档(document)、集合(collection)、数据库(database)
这三部分组成的。
MongoDB 的文档( document), 相当于关系数据库中的一行记录。
— 多个文档组成一个集合( collection), 相当于关系数据库的表。
— 多个集合( collection), 逻辑上组织在一起,就是数据库( database)。
— 一个 MongoDB 实例支持多个数据库( database)。
文档(document)、集合(collection)、数据库(database)的层次结构如下图:
MongoDB 与关系型数据库的逻辑结构对比图:
面向文档的 NoSQL 数据库主要解决的问题不是高性能的并发读写,而是保证海量数据存储的同时,具有良好的查询性能。
MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。最后由于 MongoDB 可以支持复杂的数据结构,而且带有强大的数据查询功能,因此非常受到欢迎,很多项目都考虑用 MongoDB 来替代 MySQL 等传统数据库来实现不是特别复杂的Web 应用。由于数据量实在太大,所以迁移到了 MongoDB 上面,数据查询的速度得到了非常显著的提升。
MongoDB快速入门
启动数据库
MongoDB 安装、配置完后,必须先启动它,然后才能使用它。怎么启动它呢?下面分别展示了 3 种方式来启动实例。
命令行方式启动
MongoDB 默认存储数据目录为/data/db/ (或者 c:\data\db), 默认端口 27017,默认 HTTP 端口 28017。当然你也可以修改成不同目录,只需要指定 dbpath 参数: /Apps/mongo/bin/mongod–dbpath=/data/db
[root@localhost ~]# /Apps/mongo/bin/mongod –dbpath=/data/db
Sun Apr 8 22:41:06 [initandlisten] MongoDB starting : pid=13701 port=27017 dbpath=/data/db
32-bit
……
Sun Apr 8 22:41:06 [initandlisten] waiting for connections on port 27017
Sun Apr 8 22:41:06 [websvr] web admin interface listening on port 28017
配置文件方式启动
如果是一个专业的 DBA,那么实例启动时会加很多的参数以便使系统运行的非常稳定,这样就可能会在启动时在 mongod 后面加一长串的参数,看起来非常混乱而且不好管理和维护,那么有什么办法让这些参数有条理呢? MongoDB 也支持同 mysql 一样的读取启动配置文件的方式来启动数据库,配置文件的内容如下:
[root@localhost bin]# cat /etc/mongodb.cnf
dbpath=/data/db/
启动时加上”-f”参数,并指向配置文件即可
[root@localhost bin]# ./mongod -f /etc/mongodb.cnf
Mon May 28 18:27:18 [initandlisten] MongoDB starting : pid=18481 port=27017
dbpath=/data/db/ 32-bit
……
Mon May 28 18:27:18 [initandlisten] waiting for connections on port 27017
Mon May 28 18:27:18 [websvr] web admin interface listening on port 28017
Daemon 方式启动
大家可以注意到上面的两种方式都慢在前台启动 MongoDB 进程,但当启动 MongoDB 进程的 session 窗口不小心关闭时, MongoDB 进程也将随之停止,这无疑是非常不安全的,幸好MongoDB 提供了一种后台 Daemon 方式启动的选择,只需加上一个” –fork”参数即可,这就使我们可以更方便的操作数据库的启动,但如果用到了” –fork”参数就必须也启用”–logpath”参数,这是强制的
[root@localhost ~]# /Apps/mongo/bin/mongod –dbpath=/data/db –fork
–fork has to be used with –logpath
[root@localhost ~]# /Apps/mongo/bin/mongod –dbpath=/data/db –logpath=/data/log/r3.log
–fork
all output going to: /data/log/r3.log
forked process: 19528
[root@localhost ~]#
停止数据库
MongoDB 提供的停止数据库命令也非常丰富,如果 Control-C、发送 shutdownServer()指令等db.shutdownServer()
连接数据库
现在我们就可以使用自带的 MongoDB shell 工具来操作数据库了. (我们也可以使用各种编程语言的驱动来使用 MongoDB, 但自带的 MongoDB shell 工具可以方便我们管理数据库)。新打开一个 Session 输入: /Apps/mongo/bin/mongo,如果出现下面提示,那么您就说明连接上数据库了,可以进行操作了
[root@localhost ~]# /Apps/mongo/bin/mongo
MongoDB shell version: 1.8.1
connecting to: test
>
默认 shell 连接的是本机 localhost 上面的 test 库, “connecting to:” 这个会显示你正在使用的数据库的名称. 想换数据库的话可以用”use mydb”来实现。
插入记录
下面我们来建立一个 test 的集合并写入一些数据. 建立两个对象 j 和 t , 并保存到集合中去.在例子里 “>” 来表示是 shell 输入提示符
> j = { name : “mongo” };
{“name” : “mongo”}
> t = { x : 3 };
{ “x” : 3 }
> db.things.save(j);
> db.things.save(t);
> db.things.find();
{ “_id” : ObjectId(“4c2209f9f3924d31102bd84a”), “name” : “mongo” }
{ “_id” : ObjectId(“4c2209fef3924d31102bd84b”), “x” : 3 }
>
有几点需要注意一下:
不需要预先创建一个集合. 在第一次插入数据时候会自动创建.在文档中其实可以存储任何结构的数据, 当然在实际应用我们存储的还是相同类型文档的集合. 这个特性其实可以在应用里很灵活, 你不需要类似 alter table 语句来修改你的数据结构每次插入数据时候集合中都会有一个 ID, 名字叫 _id.
查询记录
普通查询
在没有深入查询之前, 我们先看看怎么从一个查询中返回一个游标对象. 可以简单的通过find() 来查询, 他返回一个任意结构的集合. 如果实现特定的查询稍后讲解.实现上面同样的查询, 然后通过 while 来输出:
> var cursor = db.things.find();
> while (cursor.hasNext()) printjson(cursor.next());
{ “_id” : ObjectId(“4c2209f9f3924d31102bd84a”), “name” : “mongo” }
{ “_id” : ObjectId(“4c2209fef3924d31102bd84b”), “x” : 3 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd856”), “x” : 4, “j” : 1 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd857”), “x” : 4, “j” : 2 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd858”), “x” : 4, “j” : 3 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd859”), “x” : 4, “j” : 4 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd85a”), “x” : 4, “j” : 5 }
上面的例子显示了游标风格的迭代输出. hasNext() 函数告诉我们是否还有数据, 如果有则可以调用 next() 函数.当我们使用的是 JavaScript shell, 可以用到 JS 的特性, forEach 就可以输出游标了. 下面的例子就是使用 forEach() 来循环输出: forEach() 必须定义一个函数供每个游标元素调用.
> db.things.find().forEach(printjson);
{ “_id” : ObjectId(“4c2209f9f3924d31102bd84a”), “name” : “mongo” }
{ “_id” : ObjectId(“4c2209fef3924d31102bd84b”), “x” : 3 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd856”), “x” : 4, “j” : 1 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd857”), “x” : 4, “j” : 2 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd858”), “x” : 4, “j” : 3 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd859”), “x” : 4, “j” : 4 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd85a”), “x” : 4, “j” : 5 }
在 MongoDB shell 里, 我们也可以把游标当作数组来用:
> var cursor = db.things.find();
> printjson(cursor[4]);
{ “_id” : ObjectId(“4c220a42f3924d31102bd858”), “x” : 4, “j” : 3 }
使用游标时候请注意占用内存的问题, 特别是很大的游标对象, 有可能会内存溢出. 所以应该用迭代的方式来输出. 下面的示例则是把游标转换成真实的数组类型:
> var arr = db.things.find().toArray();
> arr[5];
{ “_id” : ObjectId(“4c220a42f3924d31102bd859”), “x” : 4, “j” : 4 }
请注意这些特性只是在 MongoDB shell 里使用, 而不是所有的其他应用程序驱动都支持.MongoDB 游标对象不是没有快照,如果有其他用户在集合里第一次或者最后一次调用
next(), 你可能得不到游标里的数据. 所以要明确的锁定你要查询的游标.
条件查询
到这里我们已经知道怎么从游标里实现一个查询并返回数据对象, 下面就来看看怎么根据指定的条件来查询.下面的示例就是说明如何执行一个类似 SQL 的查询, 并演示了怎么在 MongoDB 里实现. 这是在 MongoDB shell 里查询, 当然你也可以用其他的应用程序驱动或者语言来实现:
SELECT * FROM things WHERE name=”mongo”
> db.things.find({name:”mongo”}).forEach(printjson);
{ “_id” : ObjectId(“4c2209f9f3924d31102bd84a”), “name” : “mongo” }
SELECT * FROM things WHERE x=4
> db.things.find({x:4}).forEach(printjson);
{ “_id” : ObjectId(“4c220a42f3924d31102bd856”), “x” : 4, “j” : 1 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd857”), “x” : 4, “j” : 2 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd858”), “x” : 4, “j” : 3 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd859”), “x” : 4, “j” : 4 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd85a”), “x” : 4, “j” : 5 }
查询条件是 { a:A, b:B, … } 类似 “ where a==A and b==B and …” .上面显示的是所有的元素, 当然我们也可以返回特定的元素, 类似于返回表里某字段的值,只需要在 find({x:4}) 里指定元素的名字
SELECT j FROM things WHERE x=4
> db.things.find({x:4}, {j:true}).forEach(printjson);
{ “_id” : ObjectId(“4c220a42f3924d31102bd856”), “j” : 1 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd857”), “j” : 2 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd858”), “j” : 3 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd859”), “j” : 4 }
{ “_id” : ObjectId(“4c220a42f3924d31102bd85a”), “j” : 5 }
修改记录
将 name 是 mongo 的记录的 name 修改为 mongo_new
> db.things.update({name:”mongo”},{$set:{name:”mongo_new”}});
我们来查询一下是否改过来了
> db.things.find();
{ “_id” : ObjectId(“4faa9e7dedd27e6d86d86371”), “x” : 3 }
{ “_id” : ObjectId(“4faa9e7bedd27e6d86d86370”), “name” : “mongo_new” }
删除记录
将用户 name 是 mongo_new 的记录从集合 things 中删除
> db.things.remove({name:”mongo_new”});
> db.things.find();
{ “_id” : ObjectId(“4faa9e7dedd27e6d86d86371”), “x” : 3 }
经验证,该记录确实被删除了