1-MongoDB - MongoDB Python Drivers
before
在MongoDB的官方驱动页面,可以找到目前MongoDB支持的主要编程语言。
选择对应的语言,就可以根据提示下载对应的驱动,然后进行连接和操作MongoDB了。
可以用于Python的MongoDB驱动程序有两个:
- PyMongo:MongoDB推荐用于Python的驱动,也是我们本篇主要学习的。
- Motor:MongoDB推荐的Python异步驱动程序。
install
MongoDB提供PyMongo模块用于Python开发。但PyMongo模块的版本需要和MongoDB的版本对应,官网也列出了相应的版本对应列表:
更多详情参考官网:https://docs.mongodb.com/drivers/python/
这里我的Python版本是3.6.8,MongoDB的版本是3.6.12,所以,我应该选择的PyMongo的版本是3.11。
确定了版本,直接使用pip命令下载即可:
pip install pymongo==3.11
pip install -i https://pypi.doubanio.com/simple/ pymongo==3.11
connection
在连接前必须保证MongoDB服务正常运行,如果远程连接,请保持连接通道畅通。
基本模板参考
# 导入
from pymongo import MongoClient
# 连接并返回连接对象
cursor = MongoClient("mongodb://account:password@host:port/authenticationDatabase")
# 最后可以手动关闭
cursor.close()
默认连接
from pymongo import MongoClient
# 默认连接127.0.0.1:27017
cursor = MongoClient()
print(cursor.list_database_names()) # ['admin', 'config', 'local', 't1', 't2', 't3']
本地连接
from pymongo import MongoClient
# 本地无认证形式通过 127.0.0.1:27017 连接本地MongoDB服务
cursor = MongoClient("mongodb://127.0.0.1:27017/")
print(cursor.list_database_names()) # ['admin', 'config', 'local', 't1', 't2', 't3']
# 本地有认证形式通过 127.0.0.1:27017 连接本地MongoDB服务
cursor = MongoClient("mongodb://root:1234@127.0.0.1:27017/admin")
print(cursor) # MongoClient(host=['127.0.0.1:27017'], document_class=dict, tz_aware=False, connect=True)
远程连接
from pymongo import MongoClient
from urllib import parse
# 方式1,直接连接,常用
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
db = cursor.list_database_names()
print(db) # ['admin', 'config', 'local', 't1', 't2', 't3']
# 方式2,编码后连接,更安全
cursor = MongoClient("mongodb://{account}:{password}@10.0.0.200:27017/{authecticationDatabase}".format(
account=parse.quote_plus("root"),
password=parse.quote_plus("1234"),
authecticationDatabase=parse.quote_plus("admin")
))
db = cursor.list_database_names()
print(db) # ['admin', 'config', 'local', 't1', 't2', 't3']
usage
数据库管理
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 连接成功后,默认进入认证库
print(cursor.get_default_database()) # Database(MongoClient(host=['10.0.0.200:27017'], document_class=dict, tz_aware=False, connect=True), 'admin')
print(cursor.get_default_database().name) # admin
# 查看所有数据库(内置和应用)
# print(cursor.list_databases()) # <pymongo.command_cursor.CommandCursor object at 0x0000019A675A4978>
# print(cursor.list_database_names()) # ['admin', 'config', 'local', 't1', 't2', 't3']
# 删除数据库
# result = cursor.drop_database('t3')
# print(result) # 删除操作没有反回值
# print(cursor.database_names()) # ['admin', 'config', 'local', 't1', 't2']
cursor.close()
集合管理
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 当root用户登录后,默认进入admin数据库
# 首先要 use 到指定的数据库中
# t3 = cursor['t3']
t3 = cursor.get_database('t3')
# print(t3.name) # t3
# 获取 t3 数据库下所有的集合
# print(t3.list_collections()) # <pymongo.command_cursor.CommandCursor object at 0x00000249F0955D30>
# print(t3.list_collection_names()) # ['s1', 's3', 's2']
# 获取指定集合对象
# s3 = t3.get_collection('s3')
# print(s3.name) # s3
# s3 = t3['s3']
# print(s3.name) # s3
# 创建集合
# t3.create_collection('s4')
# print(t3.list_collection_names()) # ['s4', 's1', 's3', 's2']
# 删除指定集合 方式1
# result = t3.drop_collection('s1') # 存在则删除,不存在则返回 {'ok': 0.0, 'errmsg': 'ns not found', 'code': 26, 'codeName': 'NamespaceNotFound'}
# print(result)
# print(t3.list_collection_names()) # ['s3', 's2']
# 删除集合指定集合 方式2
# current_collection = t3['s2']
# result = current_collection.drop()
# print(result) # 没有返回值
# print(t3.list_collection_names()) # ['s3']
cursor.close()
添加文档
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 当root用户登录后,在admin数据库
# 首先要 use 到指定的数据库中
# t3 = cursor['t3']
t3 = cursor.get_database('t3')
# 再获取指定集合对象
s1 = t3.get_collection("s1")
# 插入一条数据
# document = {"name": "zhangkai", "age": 18, "gender": 1}
# result = s1.insert(document) # 插入并返回插入文档的 _id 值,注意,如果 _id 不手动指定,会自动生成的
# print(result) # 60091fb332d509ddcb2ad1b2
# document = {"name": "zhangkai1", "age": 19, "gender": 1}
# result = s1.insert_one(document)
# print(result) # <pymongo.results.InsertOneResult object at 0x00000188036F14C8>
# print(result.inserted_id) # 60092042bc8f685cd98f2f2a
# 插入多条数据,你也可以循环添加
# document_list = [
# {"name": "zhangkai2", "age": 20, "gender": 1},
# {"name": "xiaohong", "age": 20, "gender": 0},
# ]
# result = s1.insert_many(document_list)
# print(result) # <pymongo.results.InsertManyResult object at 0x000001EF8E687708>
# print(result.inserted_ids) # [ObjectId('600920d938e0cc822b307746'), ObjectId('600920d938e0cc822b307747')]
cursor.close()
查询文档
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 获取集合对象,通过集合对象操作集合中的数据
s5 = cursor.get_database('t1').get_collection('s5')
# s5文档解构如下:
"""
{'_id': 99, 'name': '李志强', 'age': 56, 'department': '研发', 'city': '香港', 'salary': 15993},
{'_id': 100, 'name': '王平', 'age': 45, 'department': '行政', 'city': '马鞍山', 'salary': 15113}
"""
# 统计集合中文档的数量
# print(s5.count())
# print(s5.find().count())
# 获取文档
# 获取单条文档
# print(s4.find_one())
# 获取所有文档对象,需要手动取值
# print(s5.find()) # <pymongo.cursor.Cursor object at 0x0000026BC362C320>
# for i in s5.find(): # for循环获取每篇文档
# print(i)
# print(list(s5.find())) # 使用列表转换
# 按条件过滤,在字典中编写过滤条件即可
# print(list(s5.find({"name": "zhangkai"})))
# print(list(s5.find({"info.address": "shanghai"})))
# print(list(s5.find({"age": {"$gt": 18}})))
# 分组聚合,条件跟在shell终端写的一样,所以没啥好说的
# res = s5.aggregate([
# {"$match": {
# "department": "财务"
# }}
# ])
# for i in res:
# print(i)
# 查询 id > 10 的文档,且以 department 分组,并查看每个部门的平均薪水,然后过滤平均薪水大于 25000 的
# res = s5.aggregate([
# {"$match": {"_id": {"$gt": 10}}},
# {"$group": {
# "_id": "$department", # 第一个参数必须是 _id
# "avg_salary": {"$avg": "$salary"},
# }
# },
# {"$match": {"avg_salary": {"$gt": 25000}}} # 直接引用上条结果中的 avg_salary
# ])
# print(res)
# for i in res:
# print(i)
# 查看查询语句的查询计划
# print(s5.find().explain())
更新文档
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 获取集合对象,通过集合对象操作集合中的数据
s4 = cursor.get_database('t1').get_collection('s4')
# 更新前
print(s4.find_one({"name": "likai"})) # {'_id': ObjectId('60325bdd586eff2164d3867b'), 'name': 'wangkai', 'age': 28.0}
# 更新
res = s4.update_one(
{"name": "likai"},
{"$set": {"age": 23}}
)
# 匹配的条数 更新的条数
print(res.matched_count, res.modified_count)
# 更新后
print(s4.find_one({"name": "likai"})) # {'_id': ObjectId('60325bdd586eff2164d3867c'), 'name': 'likai', 'age': 23}
# 其他更新操作都大同小异,无需多表
删除文档
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 获取集合对象,通过集合对象操作集合中的数据
s4 = cursor.get_database('t1').get_collection('s4')
# 删除前
print(s4.find_one({"name": "wangkai333"})) # {'_id': ObjectId('60325bdd586eff2164d3867b'), 'name': 'wangkai333', 'age': 23}
# 删除语句
res = s4.delete_one({"name": "wangkai333"})
# 删除后
print(s4.find_one({"name": "wangkai333"})) # None
# 其他删除操作都大同小异,无需多表
索引操作
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 首先拿到指定的集合对象
t1 = cursor.get_database('t1')
s1 = t1.get_collection('s1')
# 查看集合中所有索引
print(s1.list_indexes()) # <pymongo.command_cursor.CommandCursor object at 0x000001289F4565F8>
for index in s1.list_indexes():
print(index) # SON([('v', 2), ('key', SON([('_id', 1)])), ('name', '_id_'), ('ns', 't1.s1')])
# 可以循环取值
# for i in index.items():
# print(i) # ('v', 2)
创建和查询索引
创建索引使用:
create_index(keys, session=None, **kwargs)
create_indexes(indexes, session=None, **kwargs)
session参数一般可以省略,而kwargs
接受的常用参数有:
Parameter | Type | Description |
---|---|---|
background |
Boolean | 建索引过程会阻塞其他数据库操作,background可指定以后台方式创建索引,默认值为false。 |
unique |
Boolean | 建立的索引是否唯一,指定为true创建唯一索引,默认为false。 |
name |
String | 索引的名称,如果未指定,MongoDB通过连接索引的字段名和排序顺序生成默认的索引名。 |
droupDups |
Boolean | 3.x版本已废弃。在建立唯一索引时是否删除重复记录,指定true创建唯一索引,默认值为false。 |
sparse |
Boolean | 对文档中不存在的字段数据不启用索引,这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档,默认值为false。 |
接下来,来看具体操作吧:
from pymongo import MongoClient
# 用前先导入相关变量,如升序,降序
from pymongo import DESCENDING, ASCENDING, IndexModel
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 获取集合对象,通过集合对象操作集合中的数据
s4 = cursor.get_database('t1').get_collection('s4')
# 为age字段创建单个升序索引,默认是升序
# res = s4.create_index('age') # 简写形式
# res = s4.create_index(keys='age', name='age_1') # 手动指定索引名称
# res = s4.create_index([('age', ASCENDING)], name='age_1') # 也可以这么写
# print(res) # 返回创建的结果是索引名称:age_1
# # 创建复合索引
# res = s4.create_index([ # 列表套元组和列表套列表都行
# ('name', ASCENDING), # ASCENDING 升序
# ('age', DESCENDING), # DESCENDING 降序
# ], name="compound_index_1")
# print(res) # compound_index_1
# 在此集合上创建一个或多个索引
# id_1 = IndexModel([('name', DESCENDING)], name='name_1') # 单列索引
# id_2 = IndexModel([('name', DESCENDING), ('age', ASCENDING)], name='compound_index_2') # 复合索引
# res = s4.create_indexes([id_1, id_2])
# print(res) # ['name_1', 'compound_index_2']
# 查询所有索引
# print(s4.list_indexes()) # <pymongo.command_cursor.CommandCursor object at 0x000002200A04C6A0>
# print(list(s4.list_indexes()))
# for i in s4.list_indexes():
# print(i['name']) # age_1
# print(s4.index_information()) # 以字典的形式返回所有索引
# 虽然没有提供直接获取指定的索引,但可以通过index_information来完成
# print(s4.index_information().get('age_1')) # {'v': 2, 'key': [('age', 1)], 'ns': 't1.s4'}
重建和删除索引
首先来说重建,原来使用reindex
方法来重建索引,但该方法已被弃用,在PyMongo 4.0版本将要被移除,而且官方文档也不推荐使用了,推荐使用command命令来执行reindex
方法的功能:
from pymongo import MongoClient
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 获取db对象,使用db对象来操作
t1 = cursor.get_database('t1')
res = t1.command({"reIndex": "s4"})
print(res)
注意:重建就是把所有索引重新创建一边,重建过程是一个前台操作,意味着该重建过程会阻塞其他操作,使用要谨慎。
总之一句话:看哪个索引"不顺眼",删了重新创建是最优选择,而且要选择在夜深人静时操作。
还是来学个简单的,怎么删除索引吧!
from pymongo import MongoClient
from pymongo.errors import OperationFailure
cursor = MongoClient("mongodb://root:1234@10.0.0.200:27017/admin")
# 获取集合对象,通过集合对象操作集合中的数据
s4 = cursor.get_database('t1').get_collection('s4')
# res = s4.drop_index('age_1')
# print(res) # None 表示删除操作没有返回值
# 删除不存在的索引报错 pymongo.errors.OperationFailure ..... IndexNotFound
# 所以可以使用 try
try:
s4.drop_index('age_1')
except OperationFailure:
print('IndexNotFound')
# 清空集合中的所有索引,重复执行不报错
# s4.drop_indexes()