承诺并批量更新到数据库

Promises and upserting to database in bulk

我目前正在解析一个js对象的列表,这些对象一个一个地更新到数据库中,大致像这样 Node.js:

return promise.map(list,
    return parseItem(item)
        .then(upsertSingleItemToDB)
    ).then(all finished!)

问题是,当列表大小变得非常大(~3000 项)时,并行解析所有项会占用大量内存。使用 promise 库添加并发限制真的很容易,而不是 运行 那样内存不足(when/guard)。

但我也想优化数据库更新插入,因为 mongodb 提供了 bulkWrite 函数。由于一次解析和批量写入所有项目是不可能的,我需要将原始对象列表拆分为较小的集合,这些集合使用 promises 并行解析,然后该集合的结果数组将传递给 promified bulkWrite。如果列表项,将对其余集合重复此操作。

我很难思考如何构建较小的承诺集,以便我一次只执行一组 parseSomeItems-BulkUpsertThem(类似于 Promise.all([set1Bulk] [set2Bulk]), 其中 set1Bulk 是另一个并行解析器 Promises 数组?), 任何伪代码帮助将不胜感激(但如果这会有所不同,我正在使用)。

如果使用 mongoose 和底层 nodejs-mongodb-driver:

它看起来像这样

const saveParsedItems = items => ItemCollection.collection.bulkWrite( // accessing underlying driver
   items.map(item => ({
      updateOne: {
           filter: {id: item.id}, // or any compound key that makes your items unique for upsertion
           upsert: true,
           update: {$set: item} // should be a key:value formatted object
      }
   }))
);


const parseAndSaveItems = (items, offset = 0, limit = 3000) => { // the algorithm for retrieving items in batches be anything you want, basically
  const itemSet = items.slice(offset, limit);
  
  return Promise.all(
    itemSet.map(parseItem) // parsing all your items first
  )
    .then(saveParsedItems)
    .then(() => {
      const newOffset = offset + limit;
      if (items.length >= newOffset) {
        return parseAndSaveItemsSet(items, newOffset, limit);
      }
      
      return true;
    });
};

return parseAndSaveItems(yourItems);

第一个答案看起来很完整。但是,我想到了其他一些想法。

作为变通方法,您可以在执行下一次写入操作之前在写入操作的回调中调用超时函数。这可以让你的 CPU 和记忆在通话之间休息一下。即使您在调用之间增加一毫秒,如果您总共有 3000 个写入对象,那也只会增加 3 秒。

或者您可以分割您的 insertObjects 数组,并将它们发送到它们自己的批量写入器。