Amazon DocumentDB 文档更新 #
一、更新方法概述 #
1.1 更新方法 #
text
更新方法:
├── updateOne - 更新单个文档
├── updateMany - 更新多个文档
├── replaceOne - 替换整个文档
├── findOneAndUpdate - 查找并更新
└── findOneAndReplace - 查找并替换
1.2 更新操作符 #
text
常用更新操作符:
├── 字段操作符
│ ├── $set - 设置字段值
│ ├── $unset - 删除字段
│ ├── $setOnInsert - 插入时设置
│ ├── $inc - 数值增减
│ ├── $mul - 数值乘法
│ ├── $rename - 重命名字段
│ ├── $min - 取最小值
│ └── $max - 取最大值
│
├── 数组操作符
│ ├── $push - 添加元素
│ ├── $pull - 删除元素
│ ├── $addToSet - 添加唯一元素
│ ├── $pop - 删除首尾元素
│ └── $pullAll - 删除多个元素
│
└── 位操作符
├── $bit - 位运算
└── $ - 更新第一个匹配元素
二、updateOne - 更新单个文档 #
2.1 基本用法 #
javascript
// 更新单个文档
db.users.updateOne(
{ name: "张三" },
{ $set: { age: 31, city: "上海" } }
)
// 返回结果
{
"acknowledged": true,
"matchedCount": 1,
"modifiedCount": 1
}
2.2 $set操作符 #
javascript
// 设置字段值
db.users.updateOne(
{ _id: ObjectId("...") },
{ $set: {
name: "张三",
age: 31,
"address.city": "上海"
}}
)
// 设置嵌套字段
db.users.updateOne(
{ name: "张三" },
{ $set: { "address.province": "上海" } }
)
2.3 $unset操作符 #
javascript
// 删除字段
db.users.updateOne(
{ name: "张三" },
{ $unset: { tempField: "", deprecatedField: "" } }
)
2.4 $inc操作符 #
javascript
// 数值增减
db.products.updateOne(
{ _id: 1 },
{ $inc: { stock: -1, viewCount: 1 } }
)
// 增加多个字段
db.users.updateOne(
{ name: "张三" },
{ $inc: { loginCount: 1, score: 10 } }
)
2.5 $mul操作符 #
javascript
// 数值乘法
db.products.updateOne(
{ _id: 1 },
{ $mul: { price: 1.1 } } // 价格增加10%
)
2.6 $rename操作符 #
javascript
// 重命名字段
db.users.updateOne(
{ name: "张三" },
{ $rename: { "oldName": "newName", "addr": "address" } }
)
2.7 $min和$max操作符 #
javascript
// 设置最小值
db.products.updateOne(
{ _id: 1 },
{ $min: { price: 50 } } // 如果当前价格>50,则更新为50
)
// 设置最大值
db.products.updateOne(
{ _id: 1 },
{ $max: { stock: 100 } } // 如果当前库存<100,则更新为100
)
2.8 $setOnInsert操作符 #
javascript
// 仅在插入时设置(配合upsert使用)
db.users.updateOne(
{ email: "new@example.com" },
{
$set: { name: "新用户", updatedAt: new Date() },
$setOnInsert: { createdAt: new Date() }
},
{ upsert: true }
)
三、updateMany - 更新多个文档 #
3.1 基本用法 #
javascript
// 更新多个文档
db.users.updateMany(
{ status: "pending" },
{ $set: { status: "active", updatedAt: new Date() } }
)
// 返回结果
{
"acknowledged": true,
"matchedCount": 100,
"modifiedCount": 100
}
3.2 批量更新示例 #
javascript
// 批量更新状态
db.orders.updateMany(
{
status: "processing",
createdAt: { $lt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }
},
{ $set: { status: "timeout" } }
)
// 批量增加字段
db.products.updateMany(
{ category: "electronics" },
{ $set: { warranty: "1年" } }
)
// 批量删除字段
db.users.updateMany(
{},
{ $unset: { deprecatedField: "" } }
)
四、数组更新操作 #
4.1 $push操作符 #
javascript
// 添加数组元素
db.users.updateOne(
{ name: "张三" },
{ $push: { tags: "新标签" } }
)
// 添加多个元素
db.users.updateOne(
{ name: "张三" },
{ $push: {
scores: { $each: [90, 85, 88] }
}}
)
// 带排序和限制
db.users.updateOne(
{ name: "张三" },
{ $push: {
grades: {
$each: [85, 90, 88],
$sort: -1,
$slice: 5 // 只保留前5个
}
}}
)
// 添加到指定位置
db.users.updateOne(
{ name: "张三" },
{ $push: {
items: {
$each: ["item1", "item2"],
$position: 0 // 插入到开头
}
}}
)
4.2 $pull操作符 #
javascript
// 删除匹配元素
db.users.updateOne(
{ name: "张三" },
{ $pull: { tags: "旧标签" } }
)
// 条件删除
db.users.updateOne(
{ name: "张三" },
{ $pull: { scores: { $lt: 60 } } } // 删除小于60的分数
)
// 删除嵌套数组元素
db.users.updateOne(
{ name: "张三" },
{ $pull: { "comments": { status: "deleted" } } }
)
4.3 $pullAll操作符 #
javascript
// 删除多个指定元素
db.users.updateOne(
{ name: "张三" },
{ $pullAll: { tags: ["标签1", "标签2", "标签3"] } }
)
4.4 $addToSet操作符 #
javascript
// 添加唯一元素(不存在才添加)
db.users.updateOne(
{ name: "张三" },
{ $addToSet: { tags: "编程" } }
)
// 添加多个唯一元素
db.users.updateOne(
{ name: "张三" },
{ $addToSet: {
tags: { $each: ["阅读", "游泳", "编程"] }
}}
)
4.5 $pop操作符 #
javascript
// 删除最后一个元素
db.users.updateOne(
{ name: "张三" },
{ $pop: { tags: 1 } }
)
// 删除第一个元素
db.users.updateOne(
{ name: "张三" },
{ $pop: { tags: -1 } }
)
4.6 $位置操作符 #
javascript
// 更新第一个匹配的数组元素
db.users.updateOne(
{ "grades.subject": "数学" },
{ $set: { "grades.$.score": 95 } }
)
// 使用arrayFilters
db.users.updateOne(
{ name: "张三" },
{ $set: { "grades.$[elem].passed": true } },
{ arrayFilters: [{ "elem.score": { $gte: 60 } }] }
)
五、replaceOne - 替换文档 #
5.1 基本用法 #
javascript
// 替换整个文档(保留_id)
db.users.replaceOne(
{ _id: ObjectId("...") },
{
name: "张三",
age: 31,
email: "zhangsan@example.com",
city: "上海"
}
)
// 返回结果
{
"acknowledged": true,
"matchedCount": 1,
"modifiedCount": 1
}
5.2 与updateOne的区别 #
javascript
// updateOne - 只更新指定字段
db.users.updateOne(
{ name: "张三" },
{ $set: { age: 31 } }
)
// 结果:其他字段保留
// replaceOne - 替换整个文档
db.users.replaceOne(
{ name: "张三" },
{ name: "张三", age: 31 }
)
// 结果:只有name和age字段,其他字段被删除
六、findOneAndUpdate #
6.1 基本用法 #
javascript
// 查找并更新,返回更新前的文档
const result = db.users.findOneAndUpdate(
{ name: "张三" },
{ $inc: { loginCount: 1 } }
)
// 返回更新前的文档
{
"_id": ObjectId("..."),
"name": "张三",
"loginCount": 5
}
6.2 返回更新后的文档 #
javascript
// 返回更新后的文档
const result = db.users.findOneAndUpdate(
{ name: "张三" },
{ $inc: { loginCount: 1 } },
{ returnDocument: "after" }
)
// 返回更新后的文档
{
"_id": ObjectId("..."),
"name": "张三",
"loginCount": 6
}
6.3 其他选项 #
javascript
// 完整选项
const result = db.users.findOneAndUpdate(
{ email: "new@example.com" },
{ $set: { name: "新用户", createdAt: new Date() } },
{
returnDocument: "after",
upsert: true,
sort: { createdAt: -1 },
projection: { name: 1, email: 1 }
}
)
七、upsert操作 #
7.1 基本用法 #
javascript
// 如果存在则更新,不存在则插入
db.users.updateOne(
{ email: "zhangsan@example.com" },
{ $set: { name: "张三", age: 30 } },
{ upsert: true }
)
// 返回结果
{
"acknowledged": true,
"matchedCount": 0,
"modifiedCount": 0,
"upsertedId": ObjectId("...")
}
7.2 upsert应用场景 #
javascript
// 用户登录计数
db.users.updateOne(
{ userId: "user123" },
{
$inc: { loginCount: 1 },
$set: { lastLogin: new Date() },
$setOnInsert: { createdAt: new Date() }
},
{ upsert: true }
)
// 页面访问统计
db.pageStats.updateOne(
{ page: "/home" },
{ $inc: { views: 1 } },
{ upsert: true }
)
八、原子操作 #
8.1 条件更新 #
javascript
// 使用条件表达式
db.products.updateOne(
{
_id: 1,
stock: { $gte: 1 } // 只有库存>=1时才更新
},
{ $inc: { stock: -1 } }
)
// 返回结果检查
if (result.modifiedCount === 0) {
print("库存不足");
}
8.2 乐观锁 #
javascript
// 使用版本号实现乐观锁
function updateWithOptimisticLock(docId, updateFn) {
let retries = 3;
while (retries > 0) {
const doc = db.users.findOne({ _id: docId });
const newVersion = doc.version + 1;
const result = db.users.updateOne(
{
_id: docId,
version: doc.version
},
{
$set: updateFn(doc),
$inc: { version: 1 }
}
);
if (result.modifiedCount === 1) {
return true;
}
retries--;
}
return false;
}
8.3 原子计数器 #
javascript
// 获取并递增计数器
function getNextSequence(name) {
const result = db.counters.findOneAndUpdate(
{ _id: name },
{ $inc: { seq: 1 } },
{
returnDocument: "after",
upsert: true
}
);
return result.seq;
}
// 使用示例
const orderId = getNextSequence("order_id");
db.orders.insertOne({
_id: orderId,
items: [...]
});
九、更新选项 #
9.1 写关注 #
javascript
// 设置写关注
db.users.updateOne(
{ name: "张三" },
{ $set: { age: 31 } },
{ writeConcern: { w: "majority", j: true } }
)
9.2 数组过滤器 #
javascript
// 使用arrayFilters更新特定数组元素
db.users.updateOne(
{ name: "张三" },
{ $set: { "grades.$[elem].passed": true } },
{
arrayFilters: [
{ "elem.score": { $gte: 60 } }
]
}
)
9.3 排序选项 #
javascript
// findOneAndUpdate中使用排序
db.users.findOneAndUpdate(
{ status: "pending" },
{ $set: { status: "processing" } },
{ sort: { priority: -1 } }
)
十、性能优化 #
10.1 索引使用 #
javascript
// 确保更新条件使用索引
db.users.createIndex({ email: 1 })
// 更新时使用索引字段
db.users.updateOne(
{ email: "zhangsan@example.com" },
{ $set: { lastLogin: new Date() } }
)
10.2 批量更新优化 #
javascript
// 使用updateMany代替循环updateOne
// 不推荐
db.users.find({ status: "pending" }).forEach(user => {
db.users.updateOne(
{ _id: user._id },
{ $set: { status: "active" } }
);
});
// 推荐
db.users.updateMany(
{ status: "pending" },
{ $set: { status: "active" } }
)
10.3 更新操作优化 #
text
优化建议:
├── 使用索引字段作为更新条件
├── 避免全文档替换
├── 使用$inc代替读取-计算-写入
├── 批量更新使用updateMany
└── 合理设置写关注
十一、最佳实践 #
11.1 更新策略 #
text
更新最佳实践:
├── 使用$set只更新必要字段
├── 使用$inc进行原子计数
├── 使用upsert实现插入或更新
├── 使用条件更新实现乐观锁
└── 处理更新失败情况
11.2 错误处理 #
javascript
// 完整的错误处理
try {
const result = db.users.updateOne(
{ _id: ObjectId("...") },
{ $set: { status: "active" } }
);
if (result.matchedCount === 0) {
print("文档不存在");
} else if (result.modifiedCount === 0) {
print("文档未修改");
} else {
print("更新成功");
}
} catch (error) {
print("更新错误: " + error.message);
}
十二、总结 #
12.1 更新方法对比 #
| 方法 | 用途 | 返回值 |
|---|---|---|
| updateOne | 更新单个文档 | 更新结果 |
| updateMany | 更新多个文档 | 更新结果 |
| replaceOne | 替换整个文档 | 更新结果 |
| findOneAndUpdate | 查找并更新 | 文档 |
12.2 操作符速查 #
| 操作符 | 用途 |
|---|---|
| $set | 设置字段值 |
| $unset | 删除字段 |
| $inc | 数值增减 |
| $push | 添加数组元素 |
| $pull | 删除数组元素 |
| $addToSet | 添加唯一元素 |
下一步,让我们学习文档删除!
最后更新:2026-03-27