我目前正在使用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“混合”操作的通用界面,您将获得更多的灵活性.