【问题标题】:insert_many with upsert - PyMongo [duplicate]带有 upsert 的 insert_many - PyMongo [重复]
【发布时间】:2016-09-22 23:11:52
【问题描述】:

我有一些这样的数据:

data = [{'_id': 1, 'val': 5},
        {'_id': 2, 'val': 1}}]

数据库中的当前数据:

>>> db.collection.find_one()
    {'_id': 1, 'val': 3}

总是收到唯一的行,但不确定它们中的任何一个是否已经存在于 DB 中(例如上面的情况)。我想根据两种类型的要求更新它们。

要求 1

如果_id 已经存在,请更新行。这在某种程度上很容易:

from pymongo.errors import BulkWriteError
try:
  db.collection.insert_many(data, unordered=False)
except BulkWriteError:
  pass

执行上述操作将插入2nd 行但不会更新第一行;但它也会引发异常。

1. 有没有更好的方法来完成上述操作(用于批量插入)?

要求 2

这类似于 update_if_existsinsert if not exists 的组合。所以以下数据:

data2 = [{'_id': 1, 'val': 9},
         {'_id': 3, 'val': 4}}]

应该使用_id=1 更新行并将2nd 行插入DB。

问题是我一次得到数千行,并且不确定逐一检查和更新是否有效。

2. 在 MongoDB 中是否可以实现此要求,而无需遍历每一行并使用尽可能少的操作?

【问题讨论】:

    标签: mongodb pymongo pymongo-3.x


    【解决方案1】:

    您可以生成一个更新列表以传递给bulk write API,它将所有操作一起发送,但它们仍将在服务器上一一执行,但不会导致错误。

    from pymongo import UpdateOne
    data2 = [{'_id': 1, 'val': 9}, {'_id': 3, 'val': 4}]
    upserts=[ UpdateOne({'_id':x['_id']}, {'$setOnInsert':x}, upsert=True) for x in data2]
    result = db.test.bulk_write(upserts)
    

    从结果中可以看出,找到_id的时候是no-op,找不到的时候是insert。

    【讨论】:

    • 这不应该是unordered 吗?
    • 不,那不会达到 OP 所描述的。
    猜你喜欢
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2016-09-14
    • 2021-03-05
    • 2015-10-01
    • 1970-01-01
    相关资源
    最近更新 更多