You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Mongoose bulkWrite()中如何获取完整的新增/更新文档而非计数?

MongoDB bulkWrite 获取更新/插入后完整文档的解决方案

MongoDB 的 bulkWrite() 方法本身不支持直接返回更新或插入后的完整文档,它仅会返回操作的统计结果(即你收到的 BulkWriteResult)。要获取目标文档,你可以通过以下两种方案实现:

方案一:改用 findOneAndUpdate() 批量处理

如果你的操作量级不大,可以遍历每个操作,用 findOneAndUpdate() 替代,该方法支持返回更新后的文档。关键配置是 returnDocument: 'after'(部分旧版驱动用 new: true,二者等效)。

示例代码:

// 遍历原operations数组,转换为findOneAndUpdate的Promise数组
const operationPromises = operations.map(op => {
  const { filter, update, upsert } = op.updateOne;
  return users.findOneAndUpdate(
    filter,
    update,
    {
      upsert: upsert,
      returnDocument: 'after' // 指定返回更新后的文档
    }
  );
});

try {
  const updatedDocuments = await Promise.all(operationPromises);
  console.log(updatedDocuments); // 每个元素对应操作后的完整文档
} catch (err) {
  console.error(err);
}

方案二:先执行 bulkWrite,再批量查询文档

保持 bulkWrite() 的高性能优势,执行完批量操作后,通过筛选条件查询所有相关文档。如果存在 upsert 生成的新文档,可以结合返回的 upserted 数组中的 _id 一起查询。

示例代码:

try {
  const bulkWriteRes = await users.bulkWrite(operations);
  
  // 收集所有操作中的筛选邮箱
  const targetEmails = operations.map(op => op.updateOne.filter.email);
  // 收集upsert生成的新文档ID
  const upsertedIds = bulkWriteRes.upserted.map(item => item._id);
  
  // 查询所有目标文档
  const documents = await users.find({
    $or: [
      { email: { $in: targetEmails } },
      { _id: { $in: upsertedIds } }
    ]
  }).toArray();
  
  console.log(documents); // 包含所有更新/插入后的完整文档
} catch (err) {
  console.error(err);
}

两种方案对比

  • 方案一:优点是能直接按操作顺序获取每个文档的最新状态;缺点是循环发送请求,数据量较大时性能不如 bulkWrite()。
  • 方案二:优点是保留批量操作的高性能;缺点是需要额外执行一次查询,极端场景下(bulkWrite和find之间有其他修改)可能出现数据不一致,但大部分业务场景可忽略该风险。

内容的提问来源于stack exchange,提问作者Manish Rathod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:20:27