updateOne / updateMany 是什么
updateOne 只修改匹配到的第一条文档,updateMany 修改全部匹配文档;返回体给出 matchedCount(命中数)、modifiedCount(真正改动数)与 upsertedId(插入时的 _id)。这两个数字是核对影响面的依据,值本来就相同的文档会计入命中但不计入修改。执行条件不命中索引时,两者都会退化成逐文档扫描。
基本信息
| updateOne | 仅更新首个匹配文档 |
|---|---|
| updateMany | 更新全部匹配文档 |
| 返回值 | matchedCount / modifiedCount / upsertedId |
| 常用选项 | upsert、arrayFilters、collation |
| 原子性 | 单文档原子,多文档不保证整体原子 |
| 适用版本 | MongoDB 3.2 及以上 |
典型使用场景
- 状态批量流转:把超过时限的订单标记为过期
- 批量补字段:给历史文档补充默认值或新字段
- 批量改口径:字段名或枚举值统一调整
- 幂等写入:配合 upsert 实现有则更新无则插入
- 按条件清理标记位,供后续异步任务处理
- 定时任务统一刷新过期状态与统计字段
批量更新示例
批量更新示例
const r = db.orders.updateMany(
{ status: "pending", ts: { $lt: ISODate("2026-09-01T00:00:00Z") } },
{ $set: { status: "expired", updatedAt: new Date() } }
)
printjson(r) # 打印命中数与修改数
db.orders.countDocuments({ status: "pending", ts: { $lt: ISODate("2026-09-01T00:00:00Z") } }) # 执行前核对
db.orders.updateMany({ sku: "A-1" }, { $set: { tags: ["new"] } }, { upsert: true })返回字段读法
| 字段 | 含义 | 异常信号 |
|---|---|---|
| matchedCount | 符合条件的文档数 | 与预估差距大说明条件写错 |
| modifiedCount | 实际发生变化的文档数 | 明显小于命中数属正常 |
| upsertedId | upsert 插入文档的 _id | 出现说明原条件无匹配 |
| acknowledged | 是否被写关注确认 | 为 false 无法确认落库 |
modifiedCount 只统计真正发生变化的文档,值本来就相同的会计入 matchedCount 但不计入 modifiedCount,对账时不要把两者混为一谈。
执行前先用相同条件 countDocuments 确认命中数量,避免条件写宽误伤大范围数据;线上批量更新建议分批执行并逐批核对。
更新条件不命中索引时是逐文档扫描,集合越大越慢;给更新条件字段建索引不只是查询优化,也直接影响批量更新的耗时。