有没有办法在Pymongo 3.0中跳过insert_many的现有_id?

SLe*_*Lee 4 performance mongodb pymongo pymongo-3.x

我正在更新一个拥有数百万个文档的数据库,其中包含少于10个_id冲突.

我目前正在使用PyMongo模块使用insert_many执行批量插入:

  1. 查询数据库以查看_id是否存在
  2. 如果_id不存在,则将文档添加到数组中
  3. 使用insert_many一次插入数据库,一次1000个文档.

几百万个文档中只有大约10个冲突,我正在查询每个_id的数据库.我认为如果我可以删除查询过程,我可以减少一到两天的总插入时间.

是否存在类似于upsert的东西,如果它不存在则只插入文档?

Bla*_*ven 8

处理此问题以及以有效方式"插入/更新"许多文档的更好方法是使用批量操作API以"批次"提交所有内容,同时有效地发送所有文档并在确认中接收"单一响应".

这可以通过两种方式处理.

首先忽略主键或其他索引上的任何"重复错误",然后您可以使用"UnOrdered"操作形式:

bulk = pymongo.bulk.BulkOperationBuilder(collection,ordered=False)
for doc in docs:
    bulk.insert(doc)

response = bulk.execute()
Run Code Online (Sandbox Code Playgroud)

false那里的"UnOrdered"或参数意味着操作既可以按任何顺序执行,也可以完成"整个"批处理,只需在响应中"报告"任何实际错误.因此,这是基本上"忽略"重复项并继续前进的一种方法.

替代方法大致相同,但使用"upsert"功能以及$setOnInsert:

bulk = pymongo.bulk.BulkOperationBuilder(collection,ordered=True)
for doc in docs:
    bulk.find({ "_id": doc["_id"] }).upsert().updateOne({
        "$setOnInsert": doc
    })

response = bulk.execute()
Run Code Online (Sandbox Code Playgroud)

由此,"查询"部分.find()用于使用"主键"或者可选地使用文档的"唯一键"来查询文档的存在.如果未找到匹配项,则会在创建新文档时发生"upsert".由于所有修改内容都在$setOnInsert其中,因此仅在发生"upsert"时才修改文档字段.否则,当文档"匹配"时,实际上没有关于此运算符下保存的数据的更改.

在这种情况下,"Ordered"意味着每个语句实际上都是以它创建的"相同"顺序提交的.此处的任何"错误"都将暂停更新(在发生错误的位置),这样就不会再有操作了做出承诺.它是可选的,但可能建议正常的"重复"行为,后面的语句"复制"前一个数据.

因此,对于更高效的写入,一般的想法是使用"批量"API并相应地构建您的操作.这里的选择实际上取决于来源的"插入顺序"对您是否重要.

当然,相同的"ordered"=False操作适用insert_many于在较新的驱动程序版本中实际使用"批量"操作的操作.但是,通过坚持使用简单的API"混合"操作的通用界面,您将获得更多的灵活性.