MongoDB 更新文档

MongoDB 更新文档完整指南

(MongoDB 8.0+,2025 年最新实践)

核心结论
更新文档 = updateOne() / updateMany() / replaceOne()
支持原子操作、数组操作、管道更新、事务


一、核心更新命令对比

命令匹配条件更新方式影响文档数推荐场景
updateOne(filter, update)第一个匹配修改字段1单条更新
updateMany(filter, update)所有匹配修改字段N批量更新
replaceOne(filter, replacement)第一个匹配替换整个文档1完全重写

二、基本更新示例

1. updateOne – 更新单条

use company

// 更新张三的年龄
db.employees.updateOne(
  { name: "张三" },
  { $set: { age: 31, "address.city": "上海" } }
)

// 返回:
// { acknowledged: true, matchedCount: 1, modifiedCount: 1 }

2. updateMany – 批量更新

// 所有技术部员工加薪 10%
db.employees.updateMany(
  { department: "技术部" },
  { $mul: { salary: 1.1 } }
)

// 技术部全部标记为在职
db.employees.updateMany(
  { department: "技术部" },
  { $set: { isActive: true, updatedAt: new Date() } }
)

3. replaceOne – 完全替换

// 完全替换文档(_id 不变)
db.employees.replaceOne(
  { _id: ObjectId("671f2a1b9d8e4c2a7f1b3d5e") },
  {
    name: "张三",
    age: 31,
    role: "高级工程师",
    level: 10,
    updatedAt: new Date()
  }
)

三、更新操作符大全

操作符用途示例
$set设置字段值{ $set: { age: 18 } }
$unset删除字段{ $unset: { temp: "" } }
$inc增减数值{ $inc: { views: 1 } }
$mul乘法{ $mul: { price: 0.9 } }
$rename重命名字段{ $rename: { old: "new" } }
$setOnInsert仅在 upsert 时设置{ $setOnInsert: { createdAt: new Date() } }
$currentDate设置当前时间{ $currentDate: { lastModified: true } }

数组操作符

操作符用途
$push添加到数组末尾
$pop删除首/尾元素
$pull按条件删除
$addToSet去重添加
$定位数组中匹配的元素
// 向技能数组添加 Python(去重)
db.employees.updateOne(
  { name: "李四" },
  { $addToSet: { skills: "Python" } }
)

// 删除技能中的 SQL
db.employees.updateOne(
  { name: "李四" },
  { $pull: { skills: "SQL" } }
)

// 更新数组中第一个匹配的地址
db.employees.updateOne(
  { name: "王五", "address.city": "北京" },
  { $set: { "address.$.zip": "100001" } }
)

四、upsert(更新或插入)

// 如果不存在则插入,存在则更新年龄
db.employees.updateOne(
  { name: "赵六" },
  { 
    $set: { age: 29 },
    $setOnInsert: { 
      department: "市场部",
      hireDate: new Date(),
      createdAt: new Date()
    }
  },
  { upsert: true }
)

五、管道更新(Pipeline Update,4.2+)

支持复杂逻辑,如条件判断、变量引用。

// 只有当年龄 > 30 才加薪
db.employees.updateOne(
  { name: "张三" },
  [
    { $set: { 
        salary: {
          $cond: [
            { $gt: ["$age", 30] },
            { $multiply: ["$salary", 1.15] },
            "$salary"
          ]
        }
      }
    }
  ]
)

六、返回更新后的文档

// 返回更新后的完整文档
db.employees.findOneAndUpdate(
  { name: "张三" },
  { $set: { age: 32 } },
  { returnNewDocument: true }
)

// 或使用 aggregation pipeline
db.employees.findOneAndUpdate(
  { name: "张三" },
  [ { $set: { age: 32, updatedAt: new Date() } } ],
  { returnDocument: "after" }
)

七、事务中更新(4.0+)

const session = db.getMongo().startSession();
session.startTransaction();

try {
  db.accounts.updateOne(
    { user: "A" }, 
    { $inc: { balance: -100 } },
    { session }
  );
  db.accounts.updateOne(
    { user: "B" }, 
    { $inc: { balance: 100 } },
    { session }
  );
  session.commitTransaction();
} catch (error) {
  session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

八、性能优化建议

场景优化方式
批量更新使用 updateMany + 批量过滤
高并发使用 ordered: false(允许部分失败)
大文档避免频繁替换整个文档
索引确保过滤字段有索引
// 批量更新(允许部分失败)
db.logs.updateMany(
  { level: "error" },
  { $set: { processed: true } },
  { ordered: false }
)

九、验证更新结果

// 查看修改统计
db.employees.updateOne(...)
// → matchedCount, modifiedCount, upsertedId

// 查看更新后数据
db.employees.find({ name: "张三" }).pretty()

// 聚合统计
db.employees.aggregate([
  { $match: { department: "技术部" } },
  { $group: { _id: null, avgAge: { $avg: "$age" } } }
])

十、GUI 工具更新文档

工具操作
MongoDB Compass文档 → Edit → 修改 JSON → Save
VS Code + MongoDB文档 → 右键 → Edit Document
MongoDB Atlas文档 → Edit

十一、常见错误与解决方案

错误原因解决方案
No array filter found使用 $ 但无数组匹配检查数组字段路径
Document failed validation违反 validator检查 Schema 或加 bypassDocumentValidation
WriteConcernError副本集不可用检查集群状态
ImmutableField_id 不能修改不可变字段

十二、完整更新脚本示例

// update_employees.js
use company

print("开始批量更新员工数据...")

// 1. 技术部员工加薪 + 更新时间
const techUpdate = db.employees.updateMany(
  { department: "技术部" },
  { 
    $mul: { salary: 1.1 },
    $set: { lastRaise: new Date() }
  }
)
printjson(techUpdate)

// 2. 新员工插入(upsert)
const newHire = db.employees.updateOne(
  { name: "钱七" },
  { 
    $set: { age: 25 },
    $setOnInsert: { 
      department: "产品部",
      hireDate: new Date(),
      createdAt: new Date()
    }
  },
  { upsert: true }
)
printjson(newHire)

// 3. 替换离职员工信息
db.employees.replaceOne(
  { name: "孙八" },
  { name: "孙八", status: "离职", leaveDate: new Date() }
)

print(`共更新 ${techUpdate.modifiedCount} 名技术部员工`)
print("更新完成!")

运行:

mongosh update_employees.js

十三、一句话总结

“MongoDB 更新文档 = updateOne/Many + $set/$inc + upsert + 事务”


快速更新模板

// 单条更新
db.users.updateOne({ _id: id }, { $set: { status: "active" } })

// 批量加1
db.counters.updateMany({}, { $inc: { seq: 1 } })

// 替换文档
db.posts.replaceOne({ slug: "hello" }, newPostDoc)

官方文档

  • https://www.mongodb.com/docs/manual/reference/method/db.collection.updateOne/
  • https://www.mongodb.com/docs/manual/reference/operator/update/

如需 批量导入更新软更新(版本控制)从 SQL UPDATE 迁移实时变更流监听,欢迎继续提问!

文章已创建 2349

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部