updateBatch - 批量更新文档
概述
updateBatch 方法通过流式查询分批更新大量文档,适用于需要更新成千上万甚至百万级数据的场景,避免一次性更新造成的内存压力和性能问题。
特点
- ✅ 流式查询 - 基于
find()的流式API,恒定内存占用 - ✅ 进度监控 - 实时查看更新进度和百分比
- ✅ 错误处理 - 支持 stop/skip/collect/retry 四种策略
- ✅ 自动重试 - 网络不稳定时自动重试失败批次
- ✅ 缓存失效 - 支持显式清理相关集合缓存
- ✅ 全操作符 - 支持所有 MongoDB 更新操作符
适用场景
API 参数说明
方法签名
参数详解
第一个参数:filter(必需)
- 类型:
object - 说明:更新条件,与
updateMany相同
第二个参数:update(必需)
- 类型:
object - 说明:更新操作,必须使用更新操作符(
$set,$inc,$push等) - ❌ 错误:
{ name: 'new' } - ✅ 正确:
{ $set: { name: 'new' } }
第三个参数:options(可选)
返回值
进度回调参数
使用示例
1. 基础用法 - 批量修改状态
2. 带进度监控 - 数据迁移
输出示例:
3. $set - 设置字段值
4. $inc - 增减数值
5. $push - 添加数组元素
6. $pull - 删除数组元素
7. $mul - 乘法运算
8. 多个操作符组合
9. 使用 arrayFilters - 更新数组中的特定元素
10. 错误处理 - retry 策略(推荐)
11. 不支持 upsert
updateBatch 会先通过游标选择匹配文档的 _id,再按 _id 分批更新。这个模型没有稳定的“未匹配则插入”目标,因此 upsert: true 会被拒绝。
单文档 upsert 请使用 upsertOne();如果确实需要 MongoDB 原生多文档 update 语义,请直接使用 updateMany(..., { upsert: true })。
MongoDB 原生说明:updateMany(filter, update, { upsert: true }) 支持 upsert,但如果没有任何文档匹配,MongoDB 只会基于 filter 中的等值条件和 update 文档插入一个新文档。它不是“按输入列表逐条 upsert”。多条独立 key 的 upsert 请循环调用 upsertOne(),或使用原生 bulkWrite 的 updateOne + upsert: true 模型。
12. 复杂查询条件
性能优化建议
1. 批次大小选择
2. 索引优化
3. 避免全表扫描
4. 更新操作优化
常见问题
Q1: updateBatch 和 updateMany 有什么区别?
建议:
- 数据量 < 10000 条 → 使用
updateMany - 数据量 ≥ 10000 条 → 使用
updateBatch
Q2: updateBatch 会造成数据不一致吗?
答: updateBatch 会通过游标读取匹配文档的 _id,再按批次写入。它本身不会自动创建 MongoDB 事务,也不承诺快照隔离。如果需要事务快照,请在显式事务中执行并传入事务 session。
Q3: 为什么必须使用更新操作符?
答: 这是 MongoDB 的要求,updateMany 也是如此。
Q4: 如何批量更新 _id?
答: 不推荐更新 _id。如果必须,请使用 replaceOne 或重新插入。
Q5: updateBatch 支持哪些更新操作符?
答: 支持所有 MongoDB 更新操作符。
字段操作符:
$set- 设置字段值$unset- 删除字段$rename- 重命名字段$setOnInsert- MongoDB update 文档可包含该操作符,但只有 upsert 才有实际意义;updateBatch会拒绝upsert: true
数值操作符:
$inc- 增减$mul- 乘法$min- 取最小值$max- 取最大值
数组操作符:
$push- 添加元素$pop- 删除首/尾元素$pull- 删除匹配元素$pullAll- 删除多个元素$addToSet- 添加唯一元素
其他操作符:
$currentDate- 设置当前日期
Q6: 如何估算更新时间?
Q7: 可以在事务中使用吗?
答: 可以。