MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python MongoDB数据库的增删改查操作

2021-05-056.1k 阅读

Python 连接 MongoDB 数据库

在对 MongoDB 进行增删改查操作之前,首先需要在 Python 环境中连接到 MongoDB 数据库。要实现这一点,我们需要安装 pymongo 库。如果还没有安装,可以使用 pip install pymongo 命令进行安装。

下面是一个简单的连接示例:

import pymongo

# 创建 MongoDB 客户端,连接到本地 MongoDB 服务,默认端口是 27017
client = pymongo.MongoClient('mongodb://localhost:27017/')

# 选择一个数据库,如果数据库不存在,后续插入数据时会自动创建
db = client['test_database']

# 选择一个集合(类似于关系型数据库中的表),如果集合不存在,后续插入数据时会自动创建
collection = db['test_collection']

在上述代码中,首先通过 pymongo.MongoClient 创建了一个客户端连接到本地运行的 MongoDB 服务。mongodb://localhost:27017/ 是连接字符串,指定了 MongoDB 服务的地址和端口。

然后,通过 client['test_database'] 选择了一个数据库 test_database。如果这个数据库不存在,在后续插入数据时会自动创建。

最后,通过 db['test_collection'] 选择了一个集合 test_collection。同样,如果该集合不存在,在插入数据时会自动创建。

插入操作(增加数据)

插入单条文档

在 MongoDB 中,数据以文档(document)的形式存储,文档类似于 Python 中的字典。要插入单条文档,可以使用集合对象的 insert_one() 方法。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 定义要插入的文档
document = {
    "name": "Alice",
    "age": 30,
    "city": "New York"
}

# 插入单条文档
result = collection.insert_one(document)

# 打印插入文档的 _id
print("Inserted document ID:", result.inserted_id)

在上述代码中,首先定义了一个文档 document,它是一个字典。然后使用 collection.insert_one(document) 方法将该文档插入到集合中。insert_one() 方法返回一个 InsertOneResult 对象,通过该对象的 inserted_id 属性可以获取插入文档的唯一标识符 _id

插入多条文档

如果需要插入多条文档,可以使用 insert_many() 方法。该方法接受一个文档列表作为参数。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 定义要插入的多个文档
documents = [
    {
        "name": "Bob",
        "age": 25,
        "city": "Los Angeles"
    },
    {
        "name": "Charlie",
        "age": 35,
        "city": "Chicago"
    }
]

# 插入多条文档
result = collection.insert_many(documents)

# 打印插入文档的 _id 列表
print("Inserted document IDs:", result.inserted_ids)

在上述代码中,定义了一个包含多个文档的列表 documents。然后使用 collection.insert_many(documents) 方法将这些文档批量插入到集合中。insert_many() 方法返回一个 InsertManyResult 对象,通过其 inserted_ids 属性可以获取插入文档的 _id 列表。

查询操作(读取数据)

查询所有文档

要查询集合中的所有文档,可以使用 find() 方法。该方法返回一个游标(cursor)对象,通过遍历游标可以获取每一个文档。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 查询所有文档
cursor = collection.find()

# 遍历游标并打印文档
for document in cursor:
    print(document)

在上述代码中,collection.find() 返回一个游标对象 cursor,通过 for 循环遍历游标,就可以逐个打印出集合中的所有文档。

条件查询

find() 方法还可以接受一个查询条件作为参数,用于筛选符合条件的文档。查询条件也是一个字典形式。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 查询年龄大于 30 的文档
query = {"age": {"$gt": 30}}
cursor = collection.find(query)

# 遍历游标并打印文档
for document in cursor:
    print(document)

在上述代码中,定义了一个查询条件 query,其中 {"$gt": 30} 表示大于 30。$gt 是 MongoDB 中的一个查询操作符。通过 collection.find(query) 就可以查询出年龄大于 30 的文档。

投影查询

投影查询用于指定返回文档中需要包含的字段,通过在 find() 方法中传递第二个参数来实现。这个参数也是一个字典,其中键是字段名,值为 1 表示包含该字段,值为 0 表示排除该字段。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 只返回 name 和 age 字段
projection = {"name": 1, "age": 1, "_id": 0}
cursor = collection.find({}, projection)

# 遍历游标并打印文档
for document in cursor:
    print(document)

在上述代码中,projection 字典指定了只返回 nameage 字段,并且通过将 _id 设置为 0 来排除 _id 字段。注意,_id 字段默认是返回的,如果要排除它,必须显式设置为 0。

排序查询

可以使用 sort() 方法对查询结果进行排序。sort() 方法接受两个参数,第一个是要排序的字段名,第二个是排序方向,1 表示升序,-1 表示降序。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 按年龄升序排序
cursor = collection.find().sort("age", 1)

# 遍历游标并打印文档
for document in cursor:
    print(document)

在上述代码中,collection.find().sort("age", 1) 表示先查询所有文档,然后按 age 字段升序排序。如果要降序排序,将第二个参数改为 -1 即可。

限制查询结果数量

使用 limit() 方法可以限制查询结果返回的文档数量。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 只返回 2 条文档
cursor = collection.find().limit(2)

# 遍历游标并打印文档
for document in cursor:
    print(document)

在上述代码中,collection.find().limit(2) 表示查询所有文档,但只返回前 2 条。

更新操作(修改数据)

更新单条文档

要更新单条文档,可以使用 update_one() 方法。该方法接受两个参数,第一个是查询条件,用于确定要更新的文档,第二个是更新操作,用于指定如何更新文档。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 更新名字为 Alice 的文档,将年龄增加 1
query = {"name": "Alice"}
update = {"$inc": {"age": 1}}

result = collection.update_one(query, update)

# 打印更新的文档数量
print("Matched count:", result.matched_count)
print("Modified count:", result.modified_count)

在上述代码中,query 用于确定要更新名字为 Alice 的文档,update 中的 {"$inc": {"age": 1}} 表示将 age 字段增加 1。$inc 是 MongoDB 中的一个更新操作符。update_one() 方法返回一个 UpdateResult 对象,通过其 matched_count 属性可以获取匹配到的文档数量,通过 modified_count 属性可以获取实际被修改的文档数量。

更新多条文档

如果要更新多条符合条件的文档,可以使用 update_many() 方法,其用法与 update_one() 类似。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 更新所有年龄大于 30 的文档,将城市改为 "San Francisco"
query = {"age": {"$gt": 30}}
update = {"$set": {"city": "San Francisco"}}

result = collection.update_many(query, update)

# 打印更新的文档数量
print("Matched count:", result.matched_count)
print("Modified count:", result.modified_count)

在上述代码中,query 筛选出年龄大于 30 的文档,update 中的 {"$set": {"city": "San Francisco"}} 表示将这些文档的 city 字段设置为 San Francisco$set 是另一个常用的更新操作符。

删除操作(删除数据)

删除单条文档

要删除单条文档,可以使用 delete_one() 方法,该方法接受一个查询条件作为参数,用于确定要删除的文档。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 删除名字为 Bob 的文档
query = {"name": "Bob"}

result = collection.delete_one(query)

# 打印删除的文档数量
print("Deleted count:", result.deleted_count)

在上述代码中,query 确定要删除名字为 Bob 的文档。delete_one() 方法返回一个 DeleteResult 对象,通过其 deleted_count 属性可以获取删除的文档数量。

删除多条文档

如果要删除多条符合条件的文档,可以使用 delete_many() 方法。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 删除所有年龄小于 25 的文档
query = {"age": {"$lt": 25}}

result = collection.delete_many(query)

# 打印删除的文档数量
print("Deleted count:", result.deleted_count)

在上述代码中,query 筛选出年龄小于 25 的文档,delete_many() 方法会删除所有符合该条件的文档。同样通过 result.deleted_count 可以获取删除的文档数量。

通过以上对 Python 中 MongoDB 数据库增删改查操作的详细介绍和代码示例,希望读者能够熟练掌握在 Python 环境下对 MongoDB 进行各种数据操作的方法,从而更好地进行数据处理和应用开发。

在实际应用中,还需要考虑到数据库连接的管理、异常处理等问题。例如,在连接 MongoDB 时可能会因为网络问题或服务未启动而失败,这时就需要适当的异常处理代码来捕获并处理这些错误,以提高程序的稳定性和健壮性。

同时,对于大规模数据的操作,还需要关注性能优化。例如,合理使用索引可以大大提高查询速度。在 MongoDB 中,可以通过 create_index() 方法来创建索引。

import pymongo

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']

# 在 age 字段上创建索引
collection.create_index("age")

通过在经常用于查询条件的字段上创建索引,可以显著提升查询性能。但也要注意,索引会占用额外的存储空间,并且在插入、更新和删除操作时,数据库需要维护索引,可能会带来一定的性能开销,所以要根据实际情况权衡是否创建索引以及创建哪些索引。

另外,在进行批量操作时,要注意内存的使用情况。如果一次性插入或更新大量数据,可能会导致内存溢出等问题。可以考虑分批次进行操作,以确保程序的稳定运行。

在实际开发中,还可能会涉及到数据库的事务处理。虽然 MongoDB 在 4.0 版本之后引入了多文档事务支持,但在 Python 中使用事务时需要注意一些细节。例如,需要在客户端连接时启用事务支持,并且在事务块中执行相关的数据库操作。

import pymongo
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure, OperationFailure

try:
    client = MongoClient('mongodb://localhost:27017/', serverSelectionTimeoutMS = 5000)
    client.server_info()
except ConnectionFailure as cf:
    print("Could not connect to MongoDB: %s" % cf)

db = client['test_database']
session = client.start_session()
session.start_transaction()

try:
    collection1 = db['collection1']
    collection2 = db['collection2']

    document1 = {"name": "Transaction Test 1"}
    document2 = {"name": "Transaction Test 2"}

    collection1.insert_one(document1, session = session)
    collection2.insert_one(document2, session = session)

    session.commit_transaction()
    print("Transaction committed successfully")
except OperationFailure as of:
    session.abort_transaction()
    print("Transaction aborted: %s" % of)
finally:
    session.end_session()

在上述代码中,首先通过 client.start_session() 开启一个会话,然后在会话中通过 session.start_transaction() 启动一个事务。在事务块中执行了两个集合的插入操作,如果操作过程中没有出现异常,则通过 session.commit_transaction() 提交事务;如果出现异常,则通过 session.abort_transaction() 回滚事务。最后通过 session.end_session() 结束会话。

掌握这些细节和技巧,可以使我们在使用 Python 与 MongoDB 进行开发时更加得心应手,开发出高效、稳定的数据处理应用程序。同时,随着业务的发展和数据量的增长,不断学习和优化数据库操作方法也是非常重要的。例如,了解 MongoDB 的分布式架构和集群配置,以便在需要处理海量数据时能够构建高性能的分布式数据库系统。

在实际项目中,还可能需要将 MongoDB 与其他技术进行集成,比如将 MongoDB 作为后端数据库,与前端框架(如 React、Vue 等)结合开发 Web 应用程序。在这种情况下,需要通过 API 来暴露数据库操作接口,保证数据的安全性和可靠性。可以使用 Flask、Django 等 Python Web 框架来构建 API 服务,与 MongoDB 进行交互。

以 Flask 为例:

from flask import Flask, jsonify
import pymongo

app = Flask(__name__)

client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['test_database']
collection = db['test_collection']


@app.route('/documents', methods = ['GET'])
def get_documents():
    cursor = collection.find()
    documents = []
    for document in cursor:
        document['_id'] = str(document['_id'])
        documents.append(document)
    return jsonify(documents)


if __name__ == '__main__':
    app.run(debug = True)

在上述代码中,使用 Flask 框架创建了一个简单的 Web 应用,定义了一个路由 /documents,当客户端发送 GET 请求到该路由时,会从 MongoDB 集合中查询所有文档,并将其转换为 JSON 格式返回给客户端。需要注意的是,由于 MongoDB 的 _id 类型在 JSON 中不能直接序列化,所以将其转换为字符串类型。

通过这样的集成,可以构建出功能丰富、前后端分离的 Web 应用程序,充分发挥 MongoDB 的灵活性和 Python 的强大编程能力。同时,还可以进一步优化 API 的性能,如添加缓存机制、进行身份验证和授权等,以满足实际生产环境的需求。

总之,Python 与 MongoDB 的结合为数据处理和应用开发提供了强大的工具和灵活的解决方案。通过深入理解和掌握它们的特性及操作方法,并结合实际项目需求进行优化和扩展,可以开发出各种高效、稳定的数据驱动应用程序。无论是小型的数据分析项目,还是大型的分布式 Web 应用,都能在这一技术栈中找到合适的实现方式。