MongoDB

MongoDB 是由 C++ 编写的文档类型非关系数据库,是一个基于分布式文件系统的开源数据库系统。其内容以 BSON 的形式存储(类似JSON对象),字段值非常灵活,可以是其他文档,数组及文档数组等。

非关系数据库

非关系型数据库也叫 NoSQL ,表示 not only sql。

2009年初,Johan Oskarsson 举办了一场关于开源分布式数据库的讨论,Eric Evans 在这次讨论中提出了 NoSQL 一词,用于指代那些非关系型的,分布式的,且一般不保证遵循ACID原则的数据存储系统。Eric Evans 使用 NoSQL 这个词,并不是因为字面上的“没有 SQL ”的意思,他只是觉得很多经典的关系型数据库名字都叫“ xxSQL ”,所以为了表示跟这些关系型数据库在定位上的截然不同,就是用了“ NoSQL “一词

非关系型数据库提出了「以键值对存储,不确定结构」这种灵活的存储方式,由此也带来了和关系型数据库很多的不同:

  • 模式自由 - 不需要定义表结构
  • 逆规范化 - 不遵循范式要求,去掉完整性约束,减少表之间的依赖
  • 弹性可拓展 - 可以动态地增删节点
  • 弱事务 - 不支持ACID特性,不过可以保证事务的最终一致性
  • 多副本异步复制 - 数据快速写入一个节点,其余节点通过读取写入的日志来实现异步复制

MongoDB

优点有很多,高可用高性能易拓展面向文档等

安装与启动

Mac OS 下安装

1
brew install mongodb

启动 mongodb

1
2
3
4
5
6
#进入到安装目录
cd <mongodb installation dir>
# 开启进程
./bin/mongod
#开启shell客户端
./bin/mongo

基本概念

参考关系型数据库( RDBMS )的概念来理解,详情可以参见SQL到MongoDB映射表

MySQL MongoDB
database database
table collection
row document
column field
index index
primary key primary key

开始操作吧

创建数据库和集合
1
2
3
4
5
6
> use test
switched to db test
> db
test
> db.createCollection("users")
{ "ok" : 1 }
插入数据

db.collection.insertOne() - 插入单条数据
db.collection.insertMany() - 插入多条数据

实践一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 插入单条
> user.insertOne({"name":"zhangyang","email":"zy@123.com"})
{
"acknowledged" : true,
"insertedId" : ObjectId("5d4f0623fc2a443cf5808e28")
}

# 插入多条
> info = [{"name":"yang","email":"yang@123.com"},{"name":"peikun","email":"pk@123.com"}]
[
{
"name" : "yang",
"email" : "yang@123.com"
},
{
"name" : "peikun",
"email" : "pk@123.com"
}
]
> user.insertMany(info)
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5d4f06ebfc2a443cf5808e29"),
ObjectId("5d4f06ebfc2a443cf5808e2a")
]
}
>

查询操作

db.collection.find() - 读取文档的方法,官方文档讲得很细

1
2
3
4
5
6
7
8
9
10
11
# 指定字段查询
> user.find({"name":"yang"})
{ "_id" : ObjectId("5d4f06ebfc2a443cf5808e29"), "name" : "yang", "email" : "yang@123.com" }
# 相当于 select * from user limit 2
> user.find().limit(2)
{ "_id" : ObjectId("5d4f0623fc2a443cf5808e28"), "name" : "zhangyang", "email" : "zy@123.com" }
{ "_id" : ObjectId("5d4f06ebfc2a443cf5808e29"), "name" : "yang", "email" : "yang@123.com" }
# in 条件限制
> user.find({"name":{"$in":["peikun","yang"]}})
{ "_id" : ObjectId("5d4f06ebfc2a443cf5808e29"), "name" : "yang", "email" : "yang@123.com" }
{ "_id" : ObjectId("5d4f06ebfc2a443cf5808e2a"), "name" : "peikun", "email" : "pk@123.com" }

这里要附上比较符号表

符号 含义
$lt 小于
$gt 大于
$ne 不等于
$lte 小于等于
$gte 大于等于
$in 包括
$nin 不包括

还有通过正则表达式的方式查询

1
2
3
> user.find({"name":{"$regex":"yang$"}})
{ "_id" : ObjectId("5d4f0623fc2a443cf5808e28"), "name" : "zhangyang", "email" : "zy@123.com" }
{ "_id" : ObjectId("5d4f06ebfc2a443cf5808e29"), "name" : "yang", "email" : "yang@123.com" }

更新操作

db.collection.updateOne() - 即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新一个文档。
db.collection.updateMany() - 更新所有通过过滤条件匹配到的文档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 先查一下 原始数据
> condition = {"name":"zhangyang"}
{ "name" : "zhangyang" }
> user.find(condition).pretty()
{
"_id" : ObjectId("5d4f0623fc2a443cf5808e28"),
"name" : "zhangyang",
"email" : "zy@123.com"
}

# 调用 update() 方法
> user.updateOne(condition,{"$set":{"email":"zhangyang@123.com"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> user.find(condition).pretty()
{
"_id" : ObjectId("5d4f0623fc2a443cf5808e28"),
"name" : "zhangyang",
"email" : "zhangyang@123.com"
}
>
删除文档

db.collection.remove() - 删除符合条件的所有
db.collection.deleteOne() - 即使可能有多个文档通过过滤条件匹配到,但是也最多也只删除一个文档。
db.collection.deleteMany() - 删除所有匹配指定过滤条件的文档。

1
2
3
4
5
6
7
8
9
10
11
12
> condition = {"name":"zhangyang"}
{ "name" : "zhangyang" }
> user.find(condition).pretty()
{
"_id" : ObjectId("5d4f0623fc2a443cf5808e28"),
"name" : "zhangyang",
"email" : "zhangyang@123.com"
}
> user.remove(condition)
WriteResult({ "nRemoved" : 1 })
> user.find(condition)
> # 此时并没有输出
创建索引

db.collection.createIndex() - 使用B树数据结构

参考

感恩为以下内容付出努力的人!

  1. 非关系型数据库(nosql)介绍
  2. MongoDB官网
  3. MongoDB中文文档
  4. MongoDB中文社区
  5. Python操作MongoDB
  6. MongoDB教程