前言

通常在项目中,一般都需要一种编程语言来操作数据库,使用Python来操作数据库有着天然的优势,因为Python的字典和MongoDB的文档几乎是一样的格式,本文讲介绍如何使用Python进行MongoDB操作

1 连接数据库

1.1 安装PyMongo

使用Python操作MongoDB需要使用一个第三方库——PyMongo。安装这个库与安装Python其他的第三方库一样,使用pip安装即可:

也可以指定安装的版本:

更新 pymongo 命令:

安装完成以后,打开Python交互环境,导入PyMongo。如果不报错(如图所示),则表示安装成功

图片

1.2 连接数据库

要使用PyMongo操作MongoDB,首先需要初始化数据库连接。

(1)如果 MongoDB 就运行在本地电脑上,而且也没有修改端口或者添加用户名和密码,则初始化MongoClient的实例不需要带参数,直接写为以下格式:

(2)如果MongoDB运行在其他服务器上,则需要使用“URI(UniformResource Identifier,统一资源标志符)”来指定链接地址

MongoDB的URI格式如下:mongodb://用户名:密码@服务器IP或域名:端口例如:

(3)如果没有设置权限验证,则不需要用户名和密码,可写为

1.3 连接库与集合

PyMongo连接库与集合有两种方式

  • 方式1

连接数据库与集合的方法1

需要注意,在使用这种方式时,代码中的“数据库名”和“集合名”都不是变量名,它们直接就是库的名字和集合的名字。例如,要连接上example_data_1所在的集合,则Python代码如下:

  • 方式2

连接数据库与集合方法2

在使用这种方式时,在方括号中可以直接填变量来指定库名和集合名。当然,也可以直接填字符串,例如:

方式1 和方式2效果是完全相同的。大家可以任意选择一种自己喜欢的方式。

方式2主要用在需要批量操作数据库的情况下。例如在项目中,有时有多个测试环境,现在需要同时更新这些环境对应的数据库,则可以使用方式2。因为,这样可以将多个数据库的名字或者是多个集合的名字保存在列表中,然后再使用循环来进行操作,如下所示:

其中第3行代码,在循环里面每次连接不同的库,这样写可以同时更新多个数据库的信息,对于同一个数据库里面的多个集合,也可以使用这个方法来操作。

注意: 在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。

2 MongoDB命令在Python中的对应方法

在获取到集合连接对象collection后,就可以用这个对象的各个方法来操作MongoDB了。

虽然 MongoDB 的命令和 collection 的方法名在写法上有微小的差异,但绝大多数的MongoDB语句的参数直接复制到Python代码中都可以使用。

MongoDB的命令使用的是驼峰命名法,而PyMongo使用的是“小写字母加下划线”的方式。它们的对比见下表:

MongoDB命令PyMongo方法
insertOneinsert_one
insertManyinsert_many
findfind
updateoneupdate_one
updateManyupdate_many
deleteOnedelete_one
deleteManydelete_many

例如,Robo 3T执行的批量插入语句:

使用Python批量插入数据,代码如下:

其中,第4行代码中使用了新的集合名字,用以区别。

使用Python操作MongoDB还有一个好处:如果当前使用的库或者集合不存在,则在调用了插入方法以后,PyMongo会自动创建对应的库或集合。

总之,绝大部分的操作,直接从Robo 3T中复制到Python中都可以运行,几乎不需要修改。

3 插入数据到MongoDB

基本语法

被插入的数据格式

说明

  • MongoDB不需要提前创建数据库、不需要提前创建集合、不需要提取定义数据格式,想插入什么数据,直接插就行。
  • 同一个集合的不同行数据,字典可以不一

举例

在Python中,将字典{‘name’: ’王小六’, ‘age’: 25, ‘work’: ’厨师’}插入到MongoDB中。

具体命令如下:

提示:PyMongo还有一个通用方法——collection.insert()。

  • 如果传入的是一个字典,则collection.insert()相当于insert_one
  • 如果传入的是一个包含字典的集合,则collection.insert()相当于insert_many

但是PyMongo开发者准备移除它,因此不推荐读者在正式环境中使用这个方法。

4 从MongoDB中查询数据

查询一条数据

我们可以使用 find_one() 方法来查询集合中的一条数据,查询example_data_2 文档中的第一条数据:

输出结果:

图片

查询集合中所有数据

结果如下:

图片

逻辑查询

在Python中,从MongoDB中查询所有“age”大于21小于25,并且“name”不等于“夏侯小七”的记录。

运行效果如图所示:

图片

查询并对结果进行计数

查询并对结果进行计数

其中方向为1表示升序,方向为**-1**表示降序

对字段去重

注意:如果字段的数量很大,那么轻易不要在Robo 3T里面直接执行,否则可能导致Robo 3T卡死

5 更新/删除MongoDB中的数据

基本语法

被更新的数据

举例

在Python中更新数据和删除数据:

(1)对于“name”为“公孙小八”的记录,将“age”更新为80,将“address”更新为“美国”。

(2)删除“age”为0的数据

1.更新MongoDB中的数据

在Python中,可以使用udate_many方法来批量更新数据

更新操作还支持一个“upsert”参数。该参数的作用是:如果数据存在,则更新;如果数据不存在,则创建。

例如,对于“name”为“隐身人”的记录,将“age”改为0,将“address”改为“里世界”

由于example_data_1中没有这一条记录,因此直接更新会报错,如图所示。

图片

加上“upsert”参数,看看效果

图片

提示:如果打开了更新或插入功能,则“$set”的值是完整的文档内容,应该包含每一个字段,而不仅仅是需要被更新的字段,否则被插入的内容只有被更新的这几个字段。

2.删除MongoDB中的数据 基本语法

删除“age”为0的数据。删除语句如下:

建议先写查询语句,确认查询出来的数据就是自己想删除的数据,然后把关键字find改为delete_one或者delete_many

6 MongoDB与Python不通用的操作

绝大部分情况下,MongoDB中的命令参数直接复制到Python中就可以使用,但有一些情况例外。假设数据集example_data_2如图所示:

图片

6.1 空值

在MongoDB中,空值写作null,在Python中,空值写作None。

MongoDB不认识None,Python不认识null。

为了从数据集example_data_2中查询出所有“age”字段为空的数据,在Robo 3T中的查询语句为:

运行结果如图所示:

图片

如果直接把这段查询语句中的参数搬到Python中运行,则会导致报错,如图所示:

图片

Python会把null当作一个普通的变量,但是这个变量又没有定义,所以导致报错。

在 Python 中,要查询空值需要使用 None,对上述代码做一些修改——把“null”改为“None”,则查询成功,如图所示:

图片

6.2 布尔值

布尔值就是“真”和“假”两个值。在MongoDB中,“真”为true,“假”为false,首字母小写;在Python中,“真”为True,“假”为False,首字母大写。

在MongoDB中,查询所有student为true的记录,如图所示:

图片

如果把这段查询语句的参数直接复制到 Python 中,同样也会导致报错,因为 Python 会把true当作一个普通的变量,如图所示:

图片

把true改为True,则查询成功,如图所示:

图片

6.3 排序参数

对查询到的结果进行排序是一个常见操作,在MongoDB中,sort()命令接收一个参数,这个参数是一个字典,Key是被排序的字段名,值为1或者−1。

对于数据集example_data_2,在Robo 3T中对“age”字段进行倒序排列,如图所示:

图片

但在Python中,查询结果的sort()方法如果使用MongoDB的写法则会报错,如图所示:

图片

在Python中,sort()方法接收两个参数:第1个参数为字段名,第2个参数为-1或者1。就能够正常运行,如图所示:

图片

6.4 查询_id

在Robo 3T中,可以根据_id的值来查询文档。此时查询语句如下:

图片

在安装PyMongo的同时,Python会自动安装一个叫作“bson”的第三方库。ObjectId这个类需要从bson库中导入,具体命令如下:

运行结果如下:

图片

小结

本文首先介绍了MongoDB的安装,然后介绍了MongoDB的图形化操作软件Robo 3T。通过Robo 3T的命令输入窗口输入命令,可实现对MongoDB数据库的增、删、改、查操作。

MongoDB的大部分操作都可以平滑移植到Python中。因此,大多数情况下,直接把Robo 3T中的MongoDB操作语句复制到Python中就能使用。当然,有很小一部分情况例外。

总结