Motor插入数据前必须确保连接已建立并获取collection对象,需await client.admin.command("ping")校验连接;insert_one/many须显式await,避免协程未消费;批量插入用ordered=False实现部分成功;Pydantic模型需model_dump(by_alias=True)并处理ObjectId。

Motor插入数据前必须确保连接已建立并获取到collection对象
Motor本身不提供阻塞式连接等待,motor.motor_asyncio.AsyncIOMotorClient 实例化后立即返回,但底层连接是惰性发起的。如果没等连接就调用 insert_one,可能触发 ServerSelectionTimeoutError 或静默失败(尤其在测试环境单节点MongoDB未启动时)。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
await client.admin.command("ping")显式探测连接是否就绪,适合关键服务启动阶段校验 - 更常见做法是直接执行一次轻量操作(如
await collection.insert_one({})后立刻delete_one),但生产环境应避免这种试探写法 - 务必通过
client[db_name][collection_name]获取 collection 对象,不要复用已关闭或跨事件循环的 client
insert_one和insert_many参数差异直接影响错误处理方式
insert_one 返回一个 InsertOneResult 对象,含 inserted_id;insert_many 默认遇到任一文档校验失败(如重复唯一索引)就中断整个批量操作,并抛出 BulkWriteError。这和 PyMongo 的行为一致,但异步环境下容易误以为“只失败了一个却整批丢弃”。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 若需部分成功,传入
ordered=False参数给insert_many,此时失败项会记录在result.upserted_ids和result.bulk_api_result中 - 插入前手动检查
_id是否已存在(尤其用字符串自定义ID时),避免靠异常兜底——异步异常捕获成本比同步更高 - 注意
insert_many不接受生成器,必须传 list;若数据量大,分批(如每500条一组)再 await,防止事件循环卡顿
未 await insert_one 调用会导致数据实际未写入且无提示
这是 Motor 最常见的误用:写了 collection.insert_one({...}) 却没加 await。代码能跑通,返回一个 Coroutine 对象,但 MongoDB 服务器根本没收到请求。日志里看不到错误,数据就是不出现,排查时容易怀疑网络或权限问题。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 所有
insert_one、insert_many、update_one等写操作,必须显式await - 在 IDE 中启用类型检查(如 mypy + motor-stubs),可捕获未 await 的协程返回值被忽略的情况
- 单元测试里别只测“不报错”,要加断言:例如
assert (await collection.count_documents({})) == 1
Pydantic模型转dict再插入时要注意ObjectId和datetime兼容性
Motor 原生支持 datetime,但不自动转换 Pydantic 的 BaseModel 实例。若直接传模型对象给 insert_one,会抛 TypeError: Object of type BaseModel is not JSON serializable;而用 model.dict() 又可能丢失 ObjectId 字段(因 Pydantic 默认把 ObjectId 当成普通 object 序列化成空 dict)。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
model.model_dump(by_alias=True)(v2)或model.dict(by_alias=True)(v1),确保字段别名(如_id)正确映射 - 对含
ObjectId的字段,提前在模型中声明类型为ObjectId并设置json_encoders,或插入前手动替换:data["_id"] = ObjectId(data["_id"]) if isinstance(data.get("_id"), str) else data["_id"] - 避免在模型中用
datetime.now()作默认值——不同协程可能拿到同一毫秒级时间戳,导致测试难复现


















