python - 使用新对象更新记录
问题描述
假设我有以下 MongoDB 集合(mongomock
用于此示例,因此很容易重现):
import mongomock
collection = mongomock.MongoClient().db.collection
objects = [{'name': 'Alice', 'age': 21}, {'name': 'Bob', 'age': 20}]
collection.insert_many(objects)
然后我想用一些新对象的字段更新我现有的对象:
new_objects = [{'name': 'Alice', 'height': 170}, {'name': 'Caroline', 'height': 160}]
我能想到的唯一方法是:
for record in new_objects:
if collection.find_one({'name': record['name']}) is not None:
collection.update_one({'name': record['name']}, {'$set': {'height': record['height']}})
else:
collection.insert_one(record)
但是,如果new_objects
非常大,那么这种方法会变慢 - 有没有办法使用update_many
它?
解决方案
您不能使用update_many()
,因为它需要一个过滤器,在您的用例中它不起作用,因为每个过滤器都不同。
一个更简单的构造用于upsert=True
避免插入/更新逻辑,并且还设置了记录中指定的所有字段,编码更少:
for record in objects + new_objects:
collection.update_one({'name': record.get('name')}, {'$set': record}, upsert=True)
如果它因大量更新而变慢,请确保name
使用(在 mongo shell 中)在字段上有一个索引:
db.collection.createIndex( { "name": 1 } )
您可以通过使用 bulk_write 操作来提高性能。工作示例:
from pymongo import MongoClient, UpdateOne
collection = MongoClient().db.collection
objects = [{'name': 'Alice', 'age': 21}, {'name': 'Bob', 'age': 20}]
new_objects = [{'name': 'Alice', 'height': 170}, {'name': 'Caroline', 'height': 160}]
updates = []
for record in objects + new_objects:
updates.append(UpdateOne({'name': record.get('name')}, {'$set': record}, upsert=True))
collection.bulk_write(updates)
for record in collection.find({}, {'_id': 0}):
print(record)
给出:
{'name': 'Alice', 'age': 21, 'height': 170}
{'name': 'Bob', 'age': 20}
{'name': 'Caroline', 'height': 160}
推荐阅读
- c# - 我的素数程序中的逻辑错误
- java - 线程同步和执行顺序
- python - Pandas 数据框在没有 for 循环的情况下遍历行
- raspberry-pi - 从笔记本电脑通过 Raspberry PI 控制 GPIO 端口
- javascript - 在 WebStorm 中更改 JSX 代码样式
- reactjs - react-router 开关正在停止状态以向下传递给子组件
- swift4 - 拐角半径仅在特定拐角处
- r - 如何防止marrangeGrob打开图形设备
- ios - 从 url (AVURLAsset) 加载后,我的肖像视频会旋转
- javascript - 正则表达式仅匹配值中的第一个字符