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

时间:2015-07-13 04:52:45

标签: performance mongodb pymongo pymongo-3.x

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

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

  1. 查询数据库以查看_id是否存在
  2. 如果_id不存在,则将文档添加到数组
  3. 一次使用insert_many,1000个文档插入数据库。
  4. 几百万个文档中只有大约10个冲突,我正在查询每个_id的数据库。我认为如果我可以删除查询过程,我可以减少一到两天的总插入时间。

    是否存在类似于upsert的内容,或者只有在文档不存在时才插入文档?

2 个答案:

答案 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