异步之舞:Motor驱动与MongoDB的CRUD交响曲
title: 异步之舞:Motor驱动与MongoDB的CRUD交响曲
date: 2025/05/19 15:30:10
updated: 2025/05/19 15:30:10
author: cmdragon
excerpt:
Motor 异步驱动是专为 Python 异步框架设计的 MongoDB 连接器,基于 asyncio 实现非阻塞 I/O 操作,提升 FastAPI 的并发处理能力。通过 CRUD 操作示例,展示了如何使用 insert_one、find、update_one 和 delete 方法进行文档的创建、查询、更新和删除。聚合管道用于统计用户年龄分布,索引优化策略包括单字段索引和复合索引,遵循 ESR 规则提升查询性能。常见报错如 ServerSelectionTimeoutError、ValidationError 和 DuplicateKeyError 的处理方法也进行了详细说明。
categories:
- 后端开发
- FastAPI
tags:
- Motor
- 异步驱动
- CRUD操作
- MongoDB
- FastAPI
- 索引优化
- 聚合管道

扫描二维码
关注或者微信搜一搜:编程智域 前端至全栈交流与成长
探索数千个预构建的 AI 应用,开启你的下一个伟大创意:https://tools.cmdragon.cn/
第二章:Motor 异步驱动与 CRUD 操作实践
1. Motor 异步驱动原理
MongoDB 的异步驱动 Motor 是专为 Python 异步框架设计的数据库连接器,其底层基于 asyncio 实现非阻塞 I/O 操作。与同步驱动相比,Motor
在执行数据库操作时不会阻塞事件循环,这使得 FastAPI 能够同时处理更多并发请求。
示例场景:想象餐厅里一个服务员(事件循环)同时服务多桌客人(请求),当某桌需要等待厨房做菜(数据库操作)时,服务员会先去服务其他餐桌,等厨房完成后再回来继续服务。
# 安装依赖
# pip install fastapi==0.78.0 motor==2.5.0 pydantic==1.10.7
from fastapi import FastAPI
from motor.motor_asyncio import AsyncIOMotorClient
from pydantic import BaseModel
app = FastAPI()
# MongoDB 连接配置
DATABASE_URL = "mongodb://localhost:27017"
client = AsyncIOMotorClient(DATABASE_URL)
db = client["mydatabase"]
users_collection = db["users"]
class UserCreate(BaseModel):
name: str
age: int
email: str
class UserResponse(UserCreate):
id: str
2. CRUD 操作实现
2.1 创建文档
使用 insert_one 方法实现数据插入:
@app.post("/users", response_model=UserResponse)
async def create_user(user: UserCreate):
user_dict = user.dict()
result = await users_collection.insert_one(user_dict)
created_user = await users_collection.find_one({"_id": result.inserted_id})
return {**created_user, "id": str(created_user["_id"])}
2.2 查询文档
实现多条件查询和分页:
@app.get("/users", response_model=list[UserResponse])
async def get_users(skip: int = 0, limit: int = 10):
users = []
query = {"age": {"$gte": 18}} # 查询18岁以上用户
projection = {"_id": 0, "id": {"$toString": "$_id"}, "name": 1, "age": 1} # 字段投影
async for user in users_collection.find(query).skip(skip).limit(limit).project(projection):
users.append(user)
return users
2.3 更新文档
使用原子操作实现安全更新:
@app.put("/users/{user_id}")
async def update_user(user_id: str, user_update: UserCreate):
update_result = await users_collection.update_one(
{"_id": user_id},
{"$set": user_update.dict(exclude_unset=True)}
)
return {"modified_count": update_result.modified_count}
2.4 删除文档
软删除实现示例:
@app.delete("/users/{user_id}")
async def delete_user(user_id: str):
result = await users_collection.update_one(
{"_id": user_id},
{"$set": {"is_deleted": True}}
)
return {"modified_count": result.modified_count}
3. 聚合管道应用
统计用户年龄分布:
@app.get("/users/age-stats")
async def get_age_stats():
pipeline = [
{"$match": {"is_deleted": {"$ne": True}}},
{"$group": {
"_id": None,
"averageAge": {"$avg": "$age"},
"minAge": {"$min": "$age"},
"maxAge": {"$max": "$age"}
}}
]
result = await users_collection.aggregate(pipeline).to_list(1)
return result[0] if result else {}
4. 索引优化策略
4.1 单字段索引
# 创建索引
async def create_indexes():
await users_collection.create_index("email", unique=True)
await users_collection.create_index([("name", "text")])
4.2 复合索引
# 针对常用查询字段创建复合索引
await users_collection.create_index([("age", 1), ("is_deleted", 1)])
索引优化建议:
- 优先为查询条件字段建立索引
- 复合索引字段顺序遵循 ESR 规则(等值→排序→范围)
- 使用覆盖索引减少文档读取
课后 Quiz
Q1:Motor 的异步特性如何提升性能?
A) 减少数据库连接数
B) 允许单线程处理多个并发请求
C) 自动压缩传输数据
D) 缓存查询结果
答案
B) 正确。异步驱动通过非阻塞 I/O 允许事件循环在处理数据库操作等待期间继续处理其他请求,提升并发处理能力。
Q2:如何防止重复插入相同 email 的用户?
A) 添加唯一索引
B) 在业务逻辑中检查
C) 使用事务
D) 以上都是
答案
D) 正确。最佳实践是同时使用数据库唯一索引(A)和业务逻辑校验(B),在并发场景下可配合事务(C)保证数据一致性。
常见报错处理
报错1:ServerSelectionTimeoutError
现象:连接 MongoDB 超时
motor.motor_asyncio.ServerSelectionTimeoutError: ...
解决:
- 检查 MongoDB 服务是否运行
- 确认连接端口(默认27017)
- 验证防火墙设置
报错2:ValidationError
现象:请求参数校验失败
{
"detail": [
{
"loc": [
"body",
"age"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
处理:
- 检查请求体是否符合 Pydantic 模型定义
- 使用
exclude_unset=True处理可选字段 - 添加自定义验证器
报错3:DuplicateKeyError
现象:违反唯一性约束
pymongo.errors.DuplicateKeyError: E11000 duplicate key error...
处理:
- 在插入前检查唯一字段
- 使用
update_one配合upsert=True - 添加唯一索引确保数据一致性
通过本章学习,您将掌握 FastAPI 与 MongoDB 集成的核心技能。建议在开发过程中使用 MongoDB Compass 可视化工具实时观察数据变化,并结合
Python 的异步特性进行压力测试,深入理解异步编程的优势。
余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:异步之舞:Motor驱动与MongoDB的CRUD交响曲 | cmdragon's Blog
往期文章归档:
- 异步之舞:FastAPI与MongoDB的深度协奏 | cmdragon's Blog
- 数据库迁移的艺术:FastAPI生产环境中的灰度发布与回滚策略 | cmdragon's Blog
- 数据库迁移的艺术:团队协作中的冲突预防与解决之道 | cmdragon's Blog
- 驾驭FastAPI多数据库:从读写分离到跨库事务的艺术 | cmdragon's Blog
- 数据库事务隔离与Alembic数据恢复的实战艺术 | cmdragon's Blog
- FastAPI与Alembic:数据库迁移的隐秘艺术 | cmdragon's Blog
- 飞行中的引擎更换:生产环境数据库迁移的艺术与科学 | cmdragon's Blog
- Alembic迁移脚本冲突的智能检测与优雅合并之道 | cmdragon's Blog
- 多数据库迁移的艺术:Alembic在复杂环境中的精妙应用 | cmdragon's Blog
- 数据库事务回滚:FastAPI中的存档与读档大法 | cmdragon's Blog
- Alembic迁移脚本:让数据库变身时间旅行者 | cmdragon's Blog
- 数据库连接池:从银行柜台到代码世界的奇妙旅程 | cmdragon's Blog
- 点赞背后的技术大冒险:分布式事务与SAGA模式 | cmdragon's Blog
- N+1查询:数据库性能的隐形杀手与终极拯救指南 | cmdragon's Blog
- FastAPI与Tortoise-ORM开发的神奇之旅 | cmdragon's Blog
- DDD分层设计与异步职责划分:让你的代码不再“异步”混乱 | cmdragon's Blog
- 异步数据库事务锁:电商库存扣减的防超卖秘籍 | cmdragon's Blog
- FastAPI中的复杂查询与原子更新指南 | cmdragon's Blog
- 深入解析Tortoise-ORM关系型字段与异步查询 | cmdragon's Blog
- FastAPI与Tortoise-ORM模型配置及aerich迁移工具 | cmdragon's Blog
- 异步IO与Tortoise-ORM的数据库 | cmdragon's Blog
- FastAPI数据库连接池配置与监控 | cmdragon's Blog
- 分布式事务在点赞功能中的实现 | cmdragon's Blog
- Tortoise-ORM级联查询与预加载性能优化 | cmdragon's Blog
- 使用Tortoise-ORM和FastAPI构建评论系统 | cmdragon's Blog
- 分层架构在博客评论功能中的应用与实现 | cmdragon's Blog
- 深入解析事务基础与原子操作原理 | cmdragon's Blog
- 掌握Tortoise-ORM高级异步查询技巧 | cmdragon's Blog
- FastAPI与Tortoise-ORM实现关系型数据库关联 | cmdragon's Blog
- Tortoise-ORM与FastAPI集成:异步模型定义与实践 | cmdragon's Blog
- 异步编程与Tortoise-ORM框架 | cmdragon's Blog
- FastAPI数据库集成与事务管理 | cmdragon's Blog
- FastAPI与SQLAlchemy数据库集成 | cmdragon's Blog
- FastAPI与SQLAlchemy数据库集成与CRUD操作 | cmdragon's Blog
- XML Sitemap
异步之舞:Motor驱动与MongoDB的CRUD交响曲的更多相关文章
- MongoDB的CRUD操作
1. 前言 在上一篇文章中,我们介绍了MongoDB.现在,我们来看下如何在MongoDB中进行常规的CRUD操作.毕竟,作为一个存储系统,它的基本功能就是对数据进行增删改查操作. MongoDB中的 ...
- C#中使用官方驱动操作MongoDB
想要在C#中使用MongoDB,首先得要有个MongoDB支持的C#版的驱动.C#版的驱动有很多种,如官方提供的,samus. 实现思路大都类似.这里我们先用官方提供的mongo-csharp-dri ...
- [转载]在C#中使用官方驱动操作MongoDB
在C#中使用官方驱动操作MongoDB 8.1)下载安装 想要在C#中使用MongoDB,首先得要有个MongoDB支持的C#版的驱动.C#版的驱动有很多种,如官方提供的,samus. 实现思路大都类 ...
- MongoDB简单CRUD场景
MongoDB简单CRUD命令操作 (1)新建数据库:use 数据库名 (2)显示所有数据库:show dbs; (3)新建集合(两种方式) 隐式创建:在创建集合的同时往集合里面添加数据---db. ...
- MongoDB学习-->命令行增删改查&JAVA驱动操作Mongodb
MongoDB 是一个基于分布式文件存储的数据库. 由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关 ...
- springboot连接mongodb进行CRUD
springboot连接mongodb进行CRUD的过程: 在执行以下操作前已安装了mongodb并创建了用户和数据库,使用Robo 3T可成功连接. 1.创建springboot项目,加入以下mav ...
- 【翻译】MongoDB指南/CRUD操作(四)
[原文地址]https://docs.mongodb.com/manual/ CRUD操作(四) 1 查询方案(Query Plans) MongoDB 查询优化程序处理查询并且针对给定可利用的索引选 ...
- 【翻译】MongoDB指南/CRUD操作(二)
[原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(二) 主要内容: 更新文档,删除文档,批量写操作,SQL与MongoDB映射图,读隔离(读关 ...
- 【翻译】MongoDB指南/CRUD操作(一)
[原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(一) 主要内容:CRUD操作简介,插入文档,查询文档. CRUD操作包括创建.读取.更新和删 ...
- C#/.NET 使用官方驱动操作MongoDB(一):插入、查询
概述 想要在C#中使用MongoDB,首先得要有个MongoDB支持的C#版的驱动. C#版的驱动有很多,这里我们先用官方提供的 MongoDB.Driver(使用 Nuget 安装),当前版本为2. ...
随机推荐
- C++最基本调用静态库的方法小结
同样是最基本的调用方法小例,希望能带来参考,感谢! 创建静态库 编辑头文件 myLib.h: #pragma once #include "stdafx.h" int add(in ...
- 写了个 CasaOS/ZimaOS 内网穿透的远程访问插件(不是 frp 或者 nps),欢迎大家测试使用
插件正在提交,应该过几天就会进入市场了. 插件访问效果大概如下: casaOS 远程界面 如果大家想先行测试可以手动下载 pr 的文件进行测试. 使用 插件会提供一个二维码,使用OpenIoThub ...
- 关于JS框架的一点想法
读了几页<vue.js设计与实现>,记录几点想法: 1.Html是根本 2.无论哪个框架,不管是运行时框架,还是编译时框架,最终都要通过标签"绘制"页面 3.这个&qu ...
- 李沐动手学深度学习V2-chap_preliminaries
李沐动手学深度学习V2 文章内容说明 本文主要是自己学习过程中的随手笔记,需要自取 课程参考B站:https://space.bilibili.com/1567748478?spm_id_from=3 ...
- minecraft mods descrip
1. [Advanced Finders]矿物探测器 mod 显示玩家周围附近矿石的方向(指针显示水平面上可到达的矿石) 探测地下深部矿脉(箭头显示最近矿脉的方向(上/下)) 发现大型矿床时发出信号( ...
- mysql基础中的基础 函数
前段时间b站看sql基础语法,在此做一总结 1.基本函数 mysql中的函数基本可以分为单行函数和分组函数,单行函数用于处理单个的数据,分组函数则是传输一组值过去进行处理.单行函数有可分为字符函数,数 ...
- Go语言中的匿名函数和闭包,简单理解
匿名函数是一种没有函数名的函数,即定义即使用:闭包作为一种携带状态的函数,我们可以简单地将它理解为"对象",因为它同时具备状态和行为. 匿名函数 匿名函数没有函数名,只有函数体,它 ...
- mysql-8.0.19-winx64.zip 的安装与卸载
一.安装 1.下载mysql 官网:https://dev.mysql.com/downloads/mysql/,本人用的目前的最新版本8.0.19,版本格式为zip,如下图 2.解压到指定路径,如下 ...
- 运维 —— IMP-00030: failed to create file import_sys for write
IMP-00030: failed to create file import_sys for writeIMP-00000: Import terminated unsuccessfully原因:操 ...
- 【C#】Winform监听USB串口设备拔插实现自动断开
[C#]Winform监听USB串口设备拔插 零.问题 最近在开发串口相关的软件,需要检测串口拔掉后主动关闭串口,因此需要检测到USB的拔插事件. 一.解决 在主窗口From类下覆盖WndProc方法 ...