我正在更新一个数据库,该数据库包含数百万个文档,其中包含少于10个_id冲突。
我目前正在使用PyMongo模块使用insert_many进行批量插入:
几百万个文档中只有大约10个冲突,我正在查询每个_id的数据库。我认为如果我可以删除查询过程,我可以减少一到两天的总插入时间。
是否存在类似于upsert的内容,或者只有在文档不存在时才插入文档?
答案 0 :(得分:8)
处理此问题的更好方法以及"插入/更新"许多文件以有效的方式使用Bulk Operations API来提交所有内容#34;批次"有效地发送所有人并收到一个"单一的回应"在确认。
这可以通过两种方式处理。
首先忽略任何"重复错误"在主键或其他索引上,您可以使用" UnOrdered"经营形式:
bulk = pymongo.bulk.BulkOperationBuilder(collection,ordered=False)
for doc in docs:
bulk.insert(doc)
response = bulk.execute()
" UnOrdered"或false
参数意味着操作可以以任何顺序执行,并且"整体"批次将完成,任何实际错误只是"报告"在回应中。所以这是基本上“忽略”#34;重复并继续前进。
替代方法大致相同,但使用" 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"发生。否则,当文档匹配时#34;对于此运算符下保存的数据,实际上没有任何改变。
" Ordered"在这种情况下意味着每个语句实际上都在"相同的"订单它是创建的。也是任何"错误"这将停止更新(在发生错误的位置),以便不再提交操作。它是可选的,但可能建议正常"复制"以后的陈述"重复的行为"前一个数据。
因此,对于更高效的写入,一般的想法是使用" Bulk" API并相应地构建您的操作。这里的选择实际上归结为"插入顺序"来源对您来说很重要。
当然,相同的"ordered"=False
操作适用于insert_many
实际使用"批量"在较新的驱动程序版本中的操作。但是,通过坚持可以“混合”的通用界面,您将获得更多的灵活性。使用简单的API进行操作。
答案 1 :(得分:0)
虽然布雷克的回答很好,但在大多数情况下,最好使用squares
参数并在重复的情况下捕获squares := make(chan int)
go func() {
max := 2
var wg sync.WaitGroup
tokens := make(chan struct{}, max)
for i := 20; i >= 1; i-- {
tokens <- struct{}{}
wg.Add(1)
go func(n int) {
defer func() { <-tokens }()
defer wg.Done()
fmt.Println("run go routine ", getGID())
squares <- Square(n)
}(i)
}
wg.Wait()
close(squares)
}()
fmt.Println("About to receive")
for s := range squares {
fmt.Println("Get square: ", s)
}
。
ordered=False