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

数据库管理

Database level operations

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()

集合管理

Collection level operations

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。

更多参数参考官档:https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.create_index

接下来,来看具体操作吧:

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()
posted @ 2021-02-22 16:22  听雨危楼  阅读(331)  评论(0编辑  收藏  举报