使用新对象更新记录
Update records with new objects
假设我有以下 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
来避免 insert/update 逻辑,并且还设置记录中指定的所有字段,编码较少:
for record in objects + new_objects:
collection.update_one({'name': record.get('name')}, {'$set': record}, upsert=True)
如果更新次数较多,速度变慢,请确保您在 name
字段上有一个索引,使用 (in 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}
假设我有以下 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
来避免 insert/update 逻辑,并且还设置记录中指定的所有字段,编码较少:
for record in objects + new_objects:
collection.update_one({'name': record.get('name')}, {'$set': record}, upsert=True)
如果更新次数较多,速度变慢,请确保您在 name
字段上有一个索引,使用 (in 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}