如何在Python异步MongoDB客户端Motor中使用findAndModify?
如何在Motor中使用findAndModify命令
PyMongo提供了现成的find_and_modify()方法,但Motor没有对应的异步封装,不过可以通过Motor的run_command()方法异步执行MongoDB原生的findAndModify命令,实现相同的功能。
以下是几种常见场景的示例:
1. 修改匹配文档并返回原文档(默认行为)
当需要找到符合条件的文档、执行更新操作,并返回更新前的原文档时,可使用如下代码:
import asyncio import motor.motor_asyncio async def modify_and_get_old_doc(): # 初始化异步客户端 client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://localhost:27017') db = client.test_db # 执行findAndModify命令 result = await db.command({ 'findAndModify': 'test_collection', # 指定操作的集合名 'query': {'status': 'active'}, # 匹配条件 'update': {'$set': {'status': 'processed'}}, # 更新操作 'sort': {'created_at': -1} # 多个匹配时,按created_at倒序取第一个 }) # 获取返回的原文档(无匹配则返回None) print("原文档:", result.get('value')) asyncio.run(modify_and_get_old_doc())
2. 修改并返回更新后的新文档
如果需要返回更新后的文档,只需添加'new': True参数:
import asyncio import motor.motor_asyncio async def modify_and_get_new_doc(): client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://localhost:27017') db = client.test_db result = await db.command({ 'findAndModify': 'test_collection', 'query': {'_id': 123}, 'update': {'$inc': {'views': 1}}, # 自增views字段 'new': True # 返回更新后的文档 }) print("更新后的文档:", result.get('value'))
3. 无匹配则插入新文档(Upsert)
当需要实现"有则更新,无则插入"的逻辑时,添加'upsert': True参数:
import asyncio import datetime import motor.motor_asyncio async def upsert_example(): client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://localhost:27017') db = client.test_db result = await db.command({ 'findAndModify': 'test_collection', 'query': {'user_id': 456}, # 插入时设置created_at,更新时自增login_count 'update': {'$setOnInsert': {'created_at': datetime.datetime.now()}, '$inc': {'login_count': 1}}, 'new': True, 'upsert': True # 无匹配时插入新文档 }) print("结果文档:", result.get('value'))
注意事项
- MongoDB原生命令是驼峰式的
findAndModify,不要写成PyMongo风格的下划线格式find_and_modify - 若没有匹配到任何文档,
result.get('value')会返回None - 所有操作必须使用
await调用,因为Motor是异步驱动 - 还可添加其他参数,比如
fields指定返回的字段,remove: True实现删除匹配文档的功能(类似find_one_and_delete)
内容的提问来源于stack exchange,提问作者andre487
相关产品推荐
相关产品推荐

