MongoDB介绍
# 8.1 MongoDB 简介
MongoDB 是用 C++ 语言编写的非关系型数据库。特点是高性能、易部署、易使用,存储数据十分方便,主要特性有:
- 面向集合存储,易于存储对象类型的数据;
- 模式自由;
- 支持动态查询;
- 支持完全索引,包含内部对象;
- 支持复制和故障恢复;
- 使用高效的二进制数据存储,包括大型对象;
- 文件存储格式为 BSON(一种JSON的扩展);
MongoDB 有广泛的使用场景,是传统关系型数据的有效补充。
网站数据:MongoDB 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
缓存:由于性能很高,MongoDB 也适合作为信息基础设施的缓存层。在系统重启之后,由MongoDB 搭建的持久化缓存可以避免下层的数据源过载。
大尺寸、低价值的数据:使用传统的关系数据库存储一些数据时可能会比较贵,在此之前,很多程序员往往会选择传统的文件进行存储。
高伸缩性的场景:MongoDB 非常适合由数十或者数百台服务器组成的数据库。
用于对象及 JSON 数据的存储:MongoDB 的 BSON 数据格式非常适合文档格式化的存储及查询。
2018 年 6 月,MongoDB 在 4.0 版本中支持 ACID 事务,成为第一个支持强事务的 NoSQL 数据库,更加扩大了其使用的范围。
# 8.1.1 基本概念
在关系型数据库中,主要由数据库(database)、表(table)、**记录(rows)**三个层次概念组成。
在 MongoDB 数据库中,主要由数据库(database)、集合(collection)、**文档对象(document)**三个层次概念组成。
对比项 | MongoDB | MySQL/Oracle |
---|---|---|
表 | 集合 | 二维表table |
表的一行数据 | 文档document | 一条记录record |
表字段 | 键key | 字段field |
字段值 | 值value | 值value |
主外键 | 无 | PK,FK |
灵活度扩展性 | 极高 | 差 |
MongoDB 里的集合对应于关系型数据库里的表,但是集合中没有列、行和关系的概念,集合中只有文档,一个文档就相当于一条记录,这体现了模式自由的特点。
- 文档(document)是 MongoDB 中数据的基本单元,非常类似于关系型数据库系统中的行(但是比行要复杂的多);
- 集合(collection)就是一组文档,如果说 MongoDB 中的文档类似于关系型数据库中的行,那么集合就如同表;
如下为官方给出的文档(document)示例,是典型的json数据。
{
"_id": "5cf0029caff5056591b0ce7d",
"firstname": "Jane",
"lastname": "Wu",
"address": {
"street": "1 Circle Rd",
"city": "Los Angeles",
"state": "CA",
"zip": "90404"
},
"hobbies": ["surfing", "coding"]
}
2
3
4
5
6
7
8
9
10
11
12
其使用的查询语言也非常方便,简单易懂。
> db.users.find({ "address.zip" : "90404" })
{ "_id": "5cf0029caff5056591b0ce7d", "firstname": "Jane", "lastname": "Wu", "address":{}}
{ "_id": "507f1f77bcf86cd799439011", "firstname": "Jon", "lastname": "Davis", "address":{}}
{ "_id": "5349b4ddd2781d08c09890f3", "firstname": "Jim", "lastname": "White", "address":{}}
{ "_id": "5bf142459b72e12b2b1b2cd", "firstname": "Jeff", "lastname": "Taylor", "address":{}}
{ "_id": "5cf003283b23d04a40d5f88a", "firstname": "Jerry", "lastname": "Miller", "address":{}}
{ "_id": "5bf142459b72e12b2b1b2cd", "firstname": "Jai", "lastname": "Williams", "address":{}}
{ "_id": "5cf0036deaa1742dd225ea35", "firstname": "Jess", "lastname": "Johnson", "address":{}}
{ "_id": "54495ad94c934721ede76d90", "firstname": "Jill", "lastname": "Brown", "address":{}}
{ "_id": "566eb3c704c7b31facbb0007", "firstname": "Janet", "lastname": "Jones", "address":{}}
{ "_id": "5a999cc461d36489a27f2563", "firstname": "Jan", "lastname":
2
3
4
5
6
7
8
9
10
11
或者这样支持事务的复杂查询:
session.start_transaction()
order = { line_items : [ { item : 5, quantity: 6 } ] }
db.orders.insertOne( order, session=session );
for x in order.line_items:
db.inventory.update(
{ _id : x.item } ,
{ $inc : { number : -1 * x.quantity } },
session=session
)
session.commit_transaction()
2
3
4
5
6
7
8
9
10
MongoDB 的单个实例可以容纳多个独立的数据库,每一个数据库都有自己的集合和权限。
MongoDB 自带简洁但功能强大的JavaScript Shell
,这个工具对于管理 MongoDB 实例和操作数据作用非常大。
每一个文档都有一个特殊的键 “_id”,它在文档所处的集合中是唯一的,相当于关系数据库中的表的主键。
MongoDB 支持的数据类型,如下表所示:
数据类型 | 描述 |
---|---|
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Min/Max keys | 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Symbol | 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 |
Binary Data | 二进制数据。用于存储二进制数据。 |
Code | 代码类型。用于在文档中存储 JavaScript 代码。 |
Regular expression | 正则表达式类型。用于存储正则表达式。 |
# 8.1.2 下载安装
MongoDB 官方提供有 Windows、Linux、macOS 等操作系统的安装包下载。本小节使用 Windows 版本进行介绍。
到官方网站 https://www.mongodb.com/download-center/community (opens new window) 下载 Windows x64 最新 4.2.1 版本的 MSI 安装包。
双击下载的mongodb-win32-x86_64-2012plus-4.2.1-signed.msi
安装文件,启动安装过程。
选择“完全”安装。
在“Install MongoDB Compass”安装步骤中,取消“Install MongoDB Compass”复选框,否则安装程序会到网上下载这个 GUI 管理工具,由于网络下载原因,会导致安装过程特别漫长。
剩余安装步骤,全部选择默认即可。
安装完毕后,检查 Windows 服务,确认 MongoDB 服务已经启动。
如果读者想使用官方 GUI 管理工具(MongoDB Compass),可以自行到 https://www.mongodb.com/download-center/compass (opens new window) 这里使用下载工具(如迅雷)快速下载,并自己安装。
# 8.1.3 安装管理工具
连接 MongoDB 有多种方式,除了可以使用 MongoDB 自带的最原始的命令窗口工具外,还可以使用功能强大的“NoSQL Manager for MongoDB”客户端 GUI 管理工具来连接 MongoDB。
到 mongodbmanager 官网 https://www.mongodbmanager.com/download (opens new window) 下载Free版本的管理工具,按照正常步骤安装即可。
安装完毕后,打开管理工具,连接到本地 MongoDB 服务器。
通过 GUI 管理工具,可以方便地看到 MongoDB 安装完毕后,默认创建了 admin、config 和 local 等 3 个数据库。
在 Database 上右键,创建数据库 test,并在 test 数据库中创建 test_collection。
在 test_collection 中创建一个文档(document),内容为官方网站首页给出的示例数据。
保存后,在界面中可查看到数据已正确保存。
如果读者安装了 MongoDB Compass,可以打开 MongoDB Compass 查看保存在 MongoDB 服务器中的数据。
个人感觉,其界面不如 NoSQL Manager for MongoDB 看起来方便。当然,读者可以选用自己顺手的 GUI 管理工具,或者直接使用命令行工具来管理,最终效果都是一样的。
# 8.1.4 常用命令
在资源管理器(C:\Program Files\MongoDB\Server\4.2\bin)下找到mongo.exe
,双击,打开 MongoDB 的命令行管理终端。
接下来,我们介绍一些 MongoDB 的命令,熟悉一下 MongoDB 的操作,更详细的 MongoDB 的操作,请参考官方文档。
显示所有的数据库:
> show dbs;
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
2
3
4
5
切换到前面创建的 test 数据库:
> use test;
switched to db test
2
创建一个名为 user 的集合:
> db.createCollection("user");
{ "ok" : 1 }
2
显示数据库中所有的集合:
> show collections;
empty_collection
test_collection
user
2
3
4
在 user 集合中插入 2 个文档:
> db.user.insert({"id":1,"name":"Kevin","age":"18"});
WriteResult({ "nInserted" : 1 })
> db.user.insert({"id":2,"name":"Roy","age":"8"});
WriteResult({ "nInserted" : 1 })
2
3
4
查询 user 集合中的所有文档:
> db.user.find();
{ "_id" : ObjectId("5de3d41cb422c3774fecc6e8"), "id" : 1, "name" : "Kevin", "age" : "18" }
{ "_id" : ObjectId("5de3d4cfb422c3774fecc6e9"), "id" : 2, "name" : "Roy", "age" : "8" }
2
3
查询 user 集合中 name=Kevin 的文档:
> db.user.find({"name":"Kevin"});
{ "_id" : ObjectId("5de3d41cb422c3774fecc6e8"), "id" : 1, "name" : "Kevin", "age" : "18" }
2
更新 user 集合中 id=1 的文档的 name 为 Kevin Zhang,并添加属性 smart,值为 The Best,并查询所有记录检查更新结果:
> db.user.update({"id":1}, {"id":1,"name":"Kevin Zhang","age":"18","smart":"The Best"})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find();
{ "_id" : ObjectId("5de3d41cb422c3774fecc6e8"), "id" : 1, "name" : "Kevin Zhang", "age" : "18", "smart" : "The Best" }
{ "_id" : ObjectId("5de3d4cfb422c3774fecc6e9"), "id" : 2, "name" : "Roy", "age" : "8" }
2
3
4
5
再添加一个文档(查询结果为 3 个文档),供后续删除练习用:
> db.user.insert({"id":3,"name":"Good Man","age":"16"});
WriteResult({ "nInserted" : 1 })
> db.user.find();
{ "_id" : ObjectId("5de3d41cb422c3774fecc6e8"), "id" : 1, "name" : "Kevin Zhang", "age" : "18", "smart" : "The Best" }
{ "_id" : ObjectId("5de3d4cfb422c3774fecc6e9"), "id" : 2, "name" : "Roy", "age" : "8" }
{ "_id" : ObjectId("5de3d790b422c3774fecc6ea"), "id" : 3, "name" : "Good Man", "age" : "16" }
2
3
4
5
6
删除 id=3 的文档,并查询检查,确认查询结果为 2 个文档:
> db.user.remove({"id":3});
WriteResult({ "nRemoved" : 1 })
> db.user.find();
{ "_id" : ObjectId("5de3d41cb422c3774fecc6e8"), "id" : 1, "name" : "Kevin Zhang", "age" : "18", "smart" : "The Best" }
{ "_id" : ObjectId("5de3d4cfb422c3774fecc6e9"), "id" : 2, "name" : "Roy", "age" : "8" }
2
3
4
5
通过 GUI 管理工具,查看数据库中集合文档的变化情况,可以清晰得看到 test 数据库中新增了 1 个 user 集合,这个集合中有 2 个文档,并且这两个文档的字段数不相同(有别于关系型数据库如 MySQL,同一张表中字段必须相同)。