MongoDB 5.0.6(Atlas)中如何基于uid通过单个查询批量更新或插入多文档
批量实现MongoDB文档的Upsert(更新或插入)操作
哎,你原来的代码思路有点问题哦,update_many在这里并不适合做每个item的单独upsert——它会把所有匹配过滤条件的文档都更新成同一个值,完全不符合你“每个传入对象对应处理一个文档”的需求。我给你两种靠谱的实现方式,按需选就行:
方法一:用bulk_write批量处理(推荐,性能更优)
当你需要处理大量数据时,bulk_write是最佳选择,它能一次性提交多个操作,减少网络往返开销。每个传入的对象对应一个UpdateOne操作,指定以uid为匹配条件,存在则更新字段,不存在则插入新文档。
from pymongo import UpdateOne # 构造批量操作列表 operations = [] for item in items: # 针对每个item生成更新/插入操作 operation = UpdateOne( {"uid": item["uid"]}, # 匹配条件:uid等于当前item的uid {"$set": { "at": item["at"], "url": item["url"], "members": item["members"] }}, # 要更新的字段 upsert=True # 开启upsert:不存在则插入 ) operations.append(operation) # 执行批量操作 result = db.collection.bulk_write(operations) # 可以查看操作结果 print(f"成功插入 {result.upserted_count} 个新文档,更新了 {result.modified_count} 个现有文档")
方法二:循环使用update_one(适合小数据量,代码更直观)
如果你的数据量不大,循环调用update_one会更易读,每个item单独处理,逻辑清晰:
insert_count = 0 update_count = 0 for item in items: result = db.collection.update_one( {"uid": item["uid"]}, {"$set": { "at": item["at"], "url": item["url"], "members": item["members"] }}, upsert=True ) # 区分是插入还是更新 if result.upserted_id: insert_count += 1 else: update_count += 1 print(f"插入了 {insert_count} 个新文档,更新了 {update_count} 个现有文档")
顺便说下你原来代码的问题
你之前写的{"_id": {"$id": ids}}是错误的:首先MongoDB没有$id这个查询操作符,其次update_many的$set参数传整个items数组,会把所有匹配的文档都改成同一个数组内容,完全不是你想要的“每个item对应一个文档”的效果哦。
内容的提问来源于stack exchange,提问作者Tom3652
相关产品推荐
相关产品推荐

