Skip to content

简介

https://docs.mongodb.com/manual/

MongoDB中文社区

官方文档中文版

中文文档

https://pymongo.readthedocs.io/en/stable/tutorial.html

https://www.runoob.com/mongodb/

简介

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

MongoDB 是一个高性能、开源、无模式的文档型数据库。
在许多场景下,它可以替代传统的关系型数据库或键-值存储方式

MongoDB 是以恶介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富、最像关系数据库的。
它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因为可以存储比较复杂的数据类型

特点及功能

MongoDB 最大的特点是支持的产讯语言非常强大,其语法类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它是一个面向集合的、模式自由的文档型数据库

面向集合

数据被分组存储在数据集中,称为一个集合(collection)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库(RDBMS)里的表(table),不同的是它不需要定义任何模式(schema)。

模式自由

对于存储在 MongoDB 数据库中的文件,不需要知道它的任何结构定义。多次提到“无模式”或“模式自由”,它到底是个什么概念呢?例如,下面两条记录可以存在于同一个集合里面,如下面的代码所示

1
2
{"welcome": "Beijing"}
{"age": 25}

文档型

我们存储的是键值对的结合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档。这个数据格式称作BSON(Binary Serialized Document Notation)

MongoDB 的特点

  • 面向集合存储,易于存储对象类型的数据
  • 模式自由
  • 支持动态查询
  • 支持完全索引,包含内部对象。
  • 支持查询
  • 支持复制和故障恢复
  • 使用高效的二进制数据存储,包括大型对象(如视频等)
  • 自动处理碎片,以支持云计算层次的扩展性
  • 支持 Python、JavaScript 及 C++ 语言的驱动程序
  • 文件存储格式为 BSON(一种 JSON 的扩展)
  • 可通过网络访问

MongoDB 的功能

  • 面向集合的存储:适合存储对象及 JSON 形式的数据
  • 动态查询:MongoDB 支持丰富的查询表达式。查询指令使用 JSON 形式的标记,可轻易查询文档中内嵌的对象及数组
  • 完整的索引支持:包括文档内嵌对象及数组。MongoDB 的查询优化器会分析查询表达式,并生成一个高效的查询计划
  • 查询监视:MongoDB 包括一系列监视工具用于分析数据库操作的性能
  • 复制及自动故障转移:MongoDB 数据库支持服务器之间的数据复制,支持主从模式及服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移
  • 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)
  • 自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器

适用场合

网站数据:MongoDB 非常适合实时插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性

缓存:由于性能高,MongoDB 也适合作为信息基础设施的缓存层。在系统重启后,由 MongoDB 搭建的持久化缓存层可以避免下层的数据源过载。

大尺寸、低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储

高伸缩性的场景:MongoDB 非常适合由数十或数百台服务器组成的数据库。MongoDB 的路线图中已经包含对 MapReduce 引擎的内置支持。

用于对象及 JSON 数据的存储:MongoDb 的 BSON 数据格式非常适合文档化格式的存储及查询

下载安装运行

https://www.mongodb.com/try/download/community

https://www.mongodb.com/download-center/enterprise

1
2
3
➜  ~ cd /usr/local
➜  local sudo tar -zxvf ~/Downloads/mongodb-macos-x86_64-enterprise-4.2.1.tgz
➜  local sudo mv mongodb-macos-x86_64-enterprise-4.2.1 mongodb

.zshrc中加上

1
export PATH=/usr/local/mongodb/bin:$PATH

运行:
首先我们创建一个数据库存储目录/data/db

1
sudo mkdir -p /data/db

启动 mongodb,默认数据库目录即为/data/db

1
sudo mongod

更新到macOS Catalina 10.15后,所有的系统文件分配到一个单独的卷宗,该卷宗文件系统属性为只读

不建议去根目录下再去创建文件夹,所以可以自动创建目录~/data/mongodb,然后指定数据库目录启动

1
2
mongod --dbpath ~/data/mongodb
mongod --dbpath ~/data/mongodb --port 27018 --bind_ip 0.0.0.0

再打开一个终端进入执行以下命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
➜  ~ cd /usr/local/mongodb/bin
➜  ./mongo

MongoDB shell version v4.2.1
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("e3aed832-7dd9-434c-868c-0ed58793a7f0") }
MongoDB server version: 4.2.1
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
    http://docs.mongodb.org/
MongoDB Enterprise > 1 + 1
2
MongoDB Enterprise >
1
2
3
4
5
6
7
8
$ mongod --version
db version v4.2.1
git version: edf6d45851c0b9ee15548f0f847df141764a317e
allocator: system
modules: enterprise
build environment:
    distarch: x86_64
    target_arch: x86_64

ubuntu 安装

https://www.mongodb.com/download-center/community

选择合适的版本,例如:

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1804-4.2.6.tgz

tar -zxvf mongodb-linux-x86_64-ubuntu1804-4.2.6.tgz

.zshrc中添加:

1
export PATH="/home/zhaoyangzhen/mongodb-linux-x86_64-ubuntu1804-4.2.6/bin:$PATH"

执行source .zshrc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
➜  ~ mongod --version
db version v4.2.6
git version: 20364840b8f1af16917e4c23c1b5f5efd8b352f8
OpenSSL version: OpenSSL 1.1.1  11 Sep 2018
allocator: tcmalloc
modules: none
build environment:
    distmod: ubuntu1804
    distarch: x86_64
    target_arch: x86_64

UI 客户端

Robo 3T

Robo 3T(1.3 版本),1.4 版本在 mac 下使用还有些问题,不建议升级

可以设置 Options -> Default View Mode -> Table Mode,感觉这种比较好用

连接 MongoDB

1
2
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)

另外,MongoClient 的第一个参数 host 还可以直接传入 MongoDB 的连接字符串,它以 mongodb 开头,例如

1
client = pymongo.MongoClient('mongodb://localhost:27017/')

这也可以达到同样的连接效果

指定数据库

MongoDb 中可以建立多个数据库,接下来我们需要指定操作哪个数据库。这里我们以 test 数据库为例来说明

1
2
3
db = client.test

print(db.list_collection_names())

这里调用 client 的 test 属性即可返回 test 数据库。当然,我们也可以这样指定

1
db = client['test']

这两种方式是等价的

操作数据库

删除数据库:

1
2
client = pymongo.MongoClient(host='127.0.0.1', port=27017)
client.drop_database('test') # 根据数据库名称删除指定的数据库

指定集合

MongoDB 的每个数据库又包含许多集合(collection),它们类似于关系型数据库中的表。

下一步需要指定要操作的集合,这里指定一个集合名称为 students。与指定数据库类似,指定集合也有两种方式

1
2
collection = db.students
collection = db['students']

这样我们便声明了一个 Collection 对象

插入数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
student = {
    'id': '23333',
    'name': 'hhh',
    'age': 18,
    'gender': 'male'
}
result = collection.insert_one(student)
print(result.inserted_id)
"""
5df18f36c62d2be990124d33
"""

我们也可以同时插入多条数据,只需要以列表形式传递即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
student1 = {
    'id': '23333',
    'name': 'hhh',
    'age': 18,
    'gender': 'male'
}
student2 = {
    'id': '66666',
    'name': '逗比',
    'age': 66,
    'gender': 'female'
}
result = collection.insert_many([student1, student2])
print(result.inserted_ids)
"""
[ObjectId('5df18f5db79b47f5eb22099a'), ObjectId('5df18f5db79b47f5eb22099b')]
"""

查询

插入数据后,我们可以利用 find_one() 或 find() 方法进行查询,其中 find_one() 查询得到的是单个结果,find() 则返回一个生成器对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
result = collection.find_one({'name': 'hhh'})
print(type(result))
print(result)
"""
<class 'dict'>
{'_id': ObjectId('5df1899a624c75bbc0b34af6'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'make'}
"""

可以发现,它的返回结果是字典类型,而且多了一个 _id 属性,这就是 MongoDB 在插入过程中自动添加的

此外,也可以根据 objectId 来查询,此时需要使用 bson 库里面的 objectid:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import pymongo
from bson.objectid import ObjectId
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
result = collection.find_one({'_id': ObjectId("5df1899a624c75bbc0b34af6")})
print(result)
"""
{'_id': ObjectId('5df1899a624c75bbc0b34af6'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'make'}
"""

如果查询结果不存在,则会返回 None

对于多条数据的查询,我们可以使用 find() 方法。
例如,这里查找年龄为 18 的数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pymongo
from bson.objectid import ObjectId
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
results = collection.find({'age': 18})
print(results)
for result in results:
    print(result)
"""
<pymongo.cursor.Cursor object at 0x10973d3c8>
{'_id': ObjectId('5df1899a624c75bbc0b34af6'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'make'}
{'_id': ObjectId('5df18e6070360281bc57a1ec'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'make'}
{'_id': ObjectId('5df18e8ddd4df78713992e12'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'make'}
{'_id': ObjectId('5df18eed9076a03d2329ba39'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'male'}
{'_id': ObjectId('5df18f36c62d2be990124d33'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'male'}
{'_id': ObjectId('5df18f52a6647fb1c0b8f264'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'male'}
{'_id': ObjectId('5df18f5db79b47f5eb22099a'), 'id': '23333', 'name': 'hhh', 'age': 18, 'gender': 'male'}
"""

返回结果是 Cursor 类型,它相当于一个生成器,我们需要遍历取到所有的结果,其中每个结果都是字典类型

如果要查询年龄大于 18 的数据,则写法如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pymongo
from bson.objectid import ObjectId
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db.students
results = collection.find({'age': {'$gt': 18}})
print(results)
for result in results:
    print(result)
"""
<pymongo.cursor.Cursor object at 0x10e4b9438>
{'_id': ObjectId('5df18eed9076a03d2329ba3a'), 'id': '66666', 'name': '逗比', 'age': 66, 'gender': 'female'}
{'_id': ObjectId('5df18f52a6647fb1c0b8f265'), 'id': '66666', 'name': '逗比', 'age': 66, 'gender': 'female'}
{'_id': ObjectId('5df18f5db79b47f5eb22099b'), 'id': '66666', 'name': '逗比', 'age': 66, 'gender': 'female'}
"""

这里的查询的条件键值已经不是单纯的数字了,而是一个字典,其键名为比较符号$gt,意思是大于,键值为 20

符号 含义 示例
$lt 小于 {'age': {'$lt': 20}}
$gt 大于 {'age': {'$gt': 20}}
$lte 小于等于 {'age': {'$lte': 20}}
$gte 大于等于 {'age': {'$gte': 20}}
$ne 不等于 {'age': {'$ne': 20}}
$in 在范围内 {'age': {'$in': [20, 23]}}
$nin 不在范围内 {'age': {'$nin': [20, 23]}}

另外,还可以进行正则匹配查询。例如,查询名字以 M 开头的学生数据

1
results = collection.find({'name': {'$regex': '^M.*'}})

这里使用 $regex 来指定正则匹配,^M.* 代表以 M 开头的正则表达式

计数

要统计查询结果有多少条数据,可以调用count_documents()方法。比如,统计所有数据条数:

1
2
3
4
5
6
7
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
count = collection.count_documents({})
print(count)
# 10

或者统计符合某个条件的数据:

1
2
3
4
5
6
7
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
count = collection.count_documents({'name': 'hhh'})
print(count)
# 7

排序

排序时,直接调用sort()方法,并在其中传入排序的字段及升降序标志即可。

1
2
3
4
5
6
7
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
results = collection.find().sort('name', pymongo.ASCENDING)
print([result['name'] for result in results])
# ['hhh', 'hhh', 'hhh', 'hhh', 'hhh', 'hhh', 'hhh', '逗比', '逗比', '逗比']

这里我们调用pymongo.ASCENDING指定升序。如果要降序排列,可以传入 pymongo.DESCENDING

偏移

在某些情况下,我们可能想只取某几个元素,这时可以利用skip()方法偏移几个位置,比如偏移 2,就忽略前两个元素,得到第三个及以后的元素:

1
2
3
4
5
6
7
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
results = collection.find().sort('name', pymongo.DESCENDING).skip(2)
print([result['name'] for result in results])
# ['逗比', 'hhh', 'hhh', 'hhh', 'hhh', 'hhh', 'hhh', 'hhh']

另外,还可以用limit()方法指定要取的结果个数,示例如下:

1
2
3
4
5
6
7
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
results = collection.find().sort('name', pymongo.DESCENDING).skip(2).limit(2)
print([result['name'] for result in results])
# ['逗比', 'hhh']

值得注意的是,在数据库数量非常庞大的时候,如千万、亿级别,最好不要使用大的偏移量来查询数据,因为这样很可能导致内存溢出。此时可以使用类似如下操作来查询:

1
2
from bson.objectid import ObjectId
collection.find({'_id': {'$gt': ObjectId('5943278c814c2602678bb2b8d')}})

这时需要记录好上次查询的 _id

更新

对于数据更新,我们可以使用update_one()update_many()方法。例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
condition = {'name': 'hhh'}
student = collection.find_one(condition)
student['age'] = 26
result = collection.update_one(condition, {'$set': student})
print(result)
print(result.matched_count, result.modified_count)
# <pymongo.results.UpdateResult object at 0x10c797f48>
# 1 1

这里调用了update_one()方法,第二个参数不能直接传入修改后的字典,而是需要使用{'$set': student}这样的形式,其返回结果是UpdateResult类型。然后分别调用matched_countmodified_count属性,可以获得匹配的数据条数和影响的数据条数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
condition = {'age': {'$gt': 20}}
student = collection.find_one(condition)
result = collection.update_one(condition, {'$inc': {'age': 1}})
print(result)
print(result.matched_count, result.modified_count)
# <pymongo.results.UpdateResult object at 0x10d1f1408>
# 1 1

这里指定查询条件为年龄大于 20,然后更新条件为{'$inc': {'age': 1}},也就是年龄加 1,执行之后会将第一条符合条件的数据年龄加一。

如果调用update_many()方法,则会将所有符合条件的数据都更新,示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
condition = {'age': {'$gt': 20}}
student = collection.find_one(condition)
result = collection.update_many(condition, {'$inc': {'age': 1}})
print(result)
print(result.matched_count, result.modified_count)
# <pymongo.results.UpdateResult object at 0x101b47d88>
# 4 4

可以看到,这时所有匹配到的数据都会被更新。

删除

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
db = client.test
collection = db['students']
result = collection.delete_one({'name': '逗比'})
print(result)
print(result.deleted_count)
result = collection.delete_many({'age': {'$lt': 27}})
print(result.deleted_count)
# <pymongo.results.DeleteResult object at 0x104150408>
# 1
# 6

其他操作

另外,PyMongo 还提供了一些组合方法,如find_one_and_delete()find_one_and_replace()find_one_and_update(),它们是查找后删除、替换和更新操作,其用法与上述方法基本一致。

另外,还可以对索引进行操作,相关方法有create_index()create_indexes()drop_index()等。

mongod 配置

首先创建数据库目录,例如~/data/mongodb。然后运行命令

1
mongod –-dbpath ~/data/mongodb

以上命令每次启动都要执行

以下命令可一劳永逸:

1
mongod --config xxx.conf

配置文件内容:

1
dbpath=/Users/nocilantro/mongodb

如何配置

https://my.oschina.net/pwd/blog/399374

可视化管理

https://github.com/mrvautin/adminMongo