必须用motor而非pymongo+asyncio.to_thread,因其是官方异步驱动,基于非阻塞i/o;而后者仅线程池包装,有开销且无法复用连接池。

直接用 motor,别碰 pymongo + asyncio.to_thread 这类绕路方案——它不真正异步,只是把同步调用扔进线程池,有额外开销且无法发挥连接池复用优势。
为什么必须用 motor 而不是“包装”pymongo
Motor 是 MongoDB 官方维护的异步驱动,底层基于 asyncio 和 libmongoc 的非阻塞 I/O 实现。而 pymongo 所有操作都阻塞事件循环,哪怕套一层 await asyncio.to_thread(client.find_one, ...),也会:
- 每次调用都新建线程,频繁创建销毁线程开销大
- 无法共享连接池,容易触发
ConnectionResetError或MaxPoolSizeExceeded - 超时、重试、SSL 握手等逻辑在子线程中难以统一控制
AsyncIOMotorClient 初始化后不能直接用
AsyncIOMotorClient 实例化只是构造一个“连接工厂”,不建立真实连接。立刻调 collection.find_one() 会静默失败或抛 RuntimeError: There is no current event loop。
正确做法是显式触发一次 I/O 来激活连接:
- ✅ 推荐:
await client.admin.command("ping")—— 最轻量探测 - ✅ 更稳妥:
async with await client.start_session()(适合事务场景) - ❌ 错误:
client = AsyncIOMotorClient(...); db = client.testdb; collection = db.users; await collection.find_one({})—— 中间没 await,连接未就绪
find() 返回 AsyncIOMotorCursor,不是 list
collection.find() 立刻返回 AsyncIOMotorCursor 对象,它不包含数据,也不支持同步迭代或索引访问。
常见错误写法:
- ❌
for doc in collection.find({})→TypeError: 'AsyncIOMotorCursor' object is not iterable - ❌
await collection.find({})[0]→TypeError: 'AsyncIOMotorCursor' object is not subscriptable
正确消费方式按场景选:
- 流式处理(内存敏感):
async for doc in collection.find({"status": "active"}): process(doc) - 小批量全量(docs = await collection.find({"type": "log"}).to_list(length=500)
- 只取一条:
doc = await collection.find_one({"_id": "abc"})(比cursor.next()更语义清晰)
insert_one / insert_many 返回值不是 dict
Motor 的插入结果对象(InsertOneResult、InsertManyResult)是封装类,不能用字典语法取字段。
典型错误:
- ❌
result["inserted_id"]→TypeError: 'InsertOneResult' object is not subscriptable - ❌
result.ids(PyMongo 写法)→ 属性不存在
正确访问方式:
-
result.inserted_id(单条,返回_id值,可能是ObjectId或字符串) -
result.inserted_ids(多条,返回list,元素类型与插入文档的_id一致) - 注意:
inserted_ids是 list,不是dict,别写成result.inserted_ids[0]["_id"]
Motor 的核心约束很明确:所有带 I/O 的方法(find_one、insert_one、update_many、delete_one、count_documents 等)都返回协程,必须 await;而获取 client/db/collection 这些对象本身不触发网络,无需 await。最容易被忽略的是——游标(AsyncIOMotorCursor)本身不执行查询,只有你用 async for 或调 to_list() 这类终端方法时才真正发请求。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











