当前位置 : 主页 > 网络安全 > 测试自动化 >

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

来源:互联网 收集:自由互联 发布时间:2021-06-22
我正在更新一个拥有数百万个文档的数据库,其中包含少于10个_id冲突. 我目前正在使用PyMongo模块使用insert_many执行批量插入: 查询数据库以查看_id是否存在 如果_id不存在,则将文档添加
我正在更新一个拥有数百万个文档的数据库,其中包含少于10个_id冲突.

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

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

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

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

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

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

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

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

response = bulk.execute()

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

替代方法大致相同,但使用“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()

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

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

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

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

网友评论