MongoDB批量插入已存在许多文档的位置

时间:2014-01-23 18:51:45

标签: node.js mongodb bulkinsert

我有一个较小的(~100)小数据文件(每个可能有10个字段)插入到MongoDB中。但是它们中的许多(可能全部,但通常是80%左右)已经存在于DB中。这些文件代表了未来几个月即将发生的事件,我每隔几天就会更新一次数据库。所以大多数事件已经在那里。

任何人都知道(或想猜测)是否更有效率:

  1. 进行批量更新,但使用continueOnError = true,例如
  2. db.collection.insert(myArray, {continueOnError: true}, callback)

    1. 进行单独插入,首先检查_ID是否存在?

    2. 首先进行大量移除(类似db.collection.delete({_id: $in : [array of all the IDs in my new documents] }),然后批量插入?

    3. 我可能会做#1,因为那是最简单的,我不认为100个文件都那么大所以它可能无关紧要,但如果有10,000个文件?我正在使用node.js驱动程序在JavaScript中执行此操作。我的背景是在Java中,异常是耗时的,这是我要问的主要原因 - “continueOnError”选项是否会耗费时间???

      补充:我认为“upsert”没有意义。这是为了更新单个文档。就我而言,代表即将发生的事件的单个文档没有改变。 (好吧,也许是,这是另一个问题)

      正在发生的事情是会添加一些新文件。

4 个答案:

答案 0 :(得分:5)

  

我的背景是在Java中,异常是耗时的,这是我要问的主要原因 - “continueOnError”选项是否会耗费时间???

Bulk InsertsContinueOnError标志仅影响批处理的行为:不是在遇到第一个错误时停止处理,而是处理完整批处理。

在MongoDB 2.4中,您只会收到批处理的单个错误,这将是遇到的最后一个错误。这意味着如果您关心捕获错误,那么最好单独插入。

批量插件与单插件的主要节省时间减少了网络往返次数。驱动程序可以将批量插入分解为mongod

批量插入是否适合此用例?

鉴于您的用例只有100%(甚至1000)的文件要插入已经存在80%的文件,使用批量插入可能没有很大的好处(特别是如果这个过程每隔几天就会发生一次)。您的小插入将分批组合,但实际上不需要将80%的文档发送到服务器。

我仍然赞成使用ContinueOnError批量插入您的删除和重新插入方法,但批量插入可能是一个不必要的早期优化,因为您正在争论的文档数量和实际需要的百分比插入

我建议您使用不同的方法进行一些运行,以了解对您的用例的实际影响。

MongoDB 2.6

作为一个领先者,MongoDB 2.5开发系列(最终将在2.6版本发布中)的批处理功能得到了显着改进。计划的功能包括支持批量upsert和累积每个文档错误,而不是每批错误。

新的write命令需要驱动程序更改才能支持,但可能会改变上面的一些假设。例如,如果ContinueOnError使用新的批处理API,您最终可能会得到80%的批量ID作为重复键的结果。

有关详细信息,请参阅MongoDB问题跟踪器中的父问题MaxMessageSizeBytes

答案 1 :(得分:3)

collection.insert(item, {continueOnError: true, safe: true}, function(err, result) {
                    if (err && err.code != "11000"){
                        throw err;
                     }

                    db.close();
                    callBack();
});

答案 2 :(得分:1)

对于您的情况,我建议您考虑提取现有文档_id的列表,然后仅发送不在该列表中的文档。虽然您可以使用updateupsert进行单独更新,但没有理由这样做。除非_id的列表非常长(成千上万),否则获取列表并进行比较会比为每个文档对数据库进行单独更新更有效(某些大百分比显然未能更新)。

我不会使用continueOnError并发送所有文件......效率较低。

答案 3 :(得分:0)

我保证使用upsert让mongo处理更新或插入逻辑,你也可以使用multi来更新符合你标准的多个文档:

来自文档:

<强> UPSERT 可选参数(如果设置为true)在没有文档与查询条件匹配时创建新文档。默认值为false,如果未找到匹配项,则不会插入新文档。此参数的语法取决于MongoDB版本。 See Upsert Parameter

<强>多 可选参数(如果设置为true)将更新满足查询条件的多个文档。如果设置为false,则更新一个文档。默认值为false。有关其他信息,请see Multi Parameter.

db.collection.update(
   <query>,
   <update>,
   { upsert: <boolean>, multi: <boolean> }
)

以下是参考文档: http://docs.mongodb.org/manual/reference/method/db.collection.update/