Mongoengine如何批量更新一批记录?

3
我想要upsert(更新或插入)一系列记录,实际上我知道mongodb从3.0版本开始支持bulk操作。
我想知道mongoengine(0.10.0)是否支持bulk upsert操作。
如果不支持,我想知道如何upsert一系列记录。我知道mongoengine支持像这样的insert批处理:
class User(Document):
    username = StringField(required=True)
    password = StringFiedl(required=True)
    meta = {'db_alias': 'user_info', 'collection': 'user', 
             'indexes': [{'fields': ['username'], 'unique': True}]
           }

def save_users(self, users):
    Users.objects.insert(users) # raise mongoengine.errors.NotUniqueError

@AndreL 实际上最后一个是我的代码 - undefined
@AndreL也许简单的架构能让你理解我,我有一个唯一键username,我只想在用户存在时插入或更新用户。 - undefined
2个回答

7
您可以直接通过访问 pymongo 驱动程序 MongoEngine 使用的基础集合对象,实际上使用批量操作 API。MongoDB 自版本 2.6 起支持批量操作。自 pymongo 驱动程序 v3 起,有新的访问方法,但是自对应驱动程序升级到 2.6 服务器版本( pymongo 2.7)以来,基本方法一直存在。
要在 MongoEngine 中获取此功能,您可以从您的类中调用未记录的._get_collection(),以返回集合对象:
bulk = Users._get_collection().initialize_ordered_bulk_op()

for user in users:  # where users is a list of dicts containing data to work on
    bulk.find({ "matchField": user['matchField'] }).upsert().replace_one(user)

bulk.execute()

或者任何其他使用批量方法的用途,例如您可能需要的.update_one()。而.upsert()是修改此类更新语句的链接方法。
在这里,您正在使用原始的Python对象,因为MongoEngine本身没有直接等效物。但是,您可以通过访问底层驱动程序中的方法来使用操作。

'Collection' 对象不可调用。如果你想在一个 'Collection' 对象上调用 'inititalize_ordered_bulk_op' 方法,那么失败是因为该方法不存在。 - undefined
1
@roger 哎呀,打错字了!应该是 initialize_ordered_bulk_op() - undefined
太感谢了,我的笨蛋!我找到了解决“原始Python对象”问题的方法,“Mongoengine Document”有一个名为to_mongo()的方法可以将其转换为字典,bulk.find({ "matchField": user['matchField'] }).upsert().replace_one(user.to_mongo()) - undefined
@roger 我并不认为这是一个问题,因为对大多数人来说,数据在实例化为类之前是一个原始对象,而且我已经知道了 to_mongo()。我的观点基本上是说,在“批量”情况下,既然你已经绕过了MongoEngine封装来存储数据,那么绕过将数据实例化为类的开销似乎是合理的。不管怎样,现在你知道了一个未记录的方法和通过pymongo使用批量API方法的用法。 - undefined

2
你可以使用 mongo.collection.Collection.bulk_write
operations = [
    pymongo.ReplaceOne({'username': user. username}, user.to_mongo(), upsert=True)
    for user in users
]
result = User._get_collection().bulk_write(operations)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接