文档更新 #
一、更新概述 #
ArangoDB提供多种更新文档的方式,包括部分更新(UPDATE)和完全替换(REPLACE)。
1.1 更新方式对比 #
| 方式 | 说明 | 保留未指定字段 |
|---|---|---|
| UPDATE | 部分更新 | 是 |
| REPLACE | 完全替换 | 否 |
1.2 文档版本 #
每次更新都会生成新的 _rev:
json
{
"_key": "user_001",
"_rev": "_abc124",
"name": "张三"
}
二、UPDATE更新 #
2.1 基本UPDATE #
aql
UPDATE "user_001" WITH {
age: 29,
city: "上海"
} IN users
2.2 使用_key更新 #
aql
UPDATE { _key: "user_001" } WITH {
age: 29
} IN users
2.3 使用_id更新 #
aql
UPDATE "users/user_001" WITH {
age: 29
} IN users
2.4 条件更新 #
aql
FOR user IN users
FILTER user.age < 18
UPDATE user WITH {
status: "minor"
} IN users
2.5 返回更新后的文档 #
aql
UPDATE "user_001" WITH {
age: 29
} IN users
RETURN NEW
2.6 返回更新前的文档 #
aql
UPDATE "user_001" WITH {
age: 29
} IN users
RETURN OLD
2.7 返回新旧文档对比 #
aql
UPDATE "user_001" WITH {
age: 29
} IN users
RETURN {
old: OLD.age,
new: NEW.age
}
三、REPLACE替换 #
3.1 基本REPLACE #
aql
REPLACE "user_001" WITH {
name: "张三",
email: "zhangsan@example.com",
city: "上海"
} IN users
3.2 条件替换 #
aql
FOR user IN users
FILTER user.status == "inactive"
REPLACE user WITH {
name: user.name,
email: user.email,
status: "deleted",
deletedAt: DATE_NOW()
} IN users
3.3 REPLACE vs UPDATE #
aql
UPDATE "user_001" WITH { age: 30 } IN users
REPLACE "user_001" WITH { name: "张三", age: 30 } IN users
四、批量更新 #
4.1 批量更新所有文档 #
aql
FOR user IN users
UPDATE user WITH {
updatedAt: DATE_NOW()
} IN users
4.2 条件批量更新 #
aql
FOR user IN users
FILTER user.city == "北京"
UPDATE user WITH {
region: "华北"
} IN users
4.3 批量更新并返回 #
aql
FOR user IN users
FILTER user.status == "pending"
UPDATE user WITH {
status: "active"
} IN users
RETURN NEW
4.4 使用表达式更新 #
aql
FOR user IN users
UPDATE user WITH {
age: user.age + 1,
updatedAt: DATE_NOW()
} IN users
五、原子更新 #
5.1 数值增减 #
aql
UPDATE "product_001" WITH {
stock: OLD.stock - 1,
sales: OLD.sales + 1
} IN products
5.2 使用OLD引用 #
aql
UPDATE "user_001" WITH {
loginCount: OLD.loginCount + 1,
lastLogin: DATE_NOW()
} IN users
5.3 数组操作 #
添加到数组:
aql
UPDATE "user_001" WITH {
hobbies: PUSH(OLD.hobbies, "摄影")
} IN users
从数组移除:
aql
UPDATE "user_001" WITH {
hobbies: REMOVE_VALUE(OLD.hobbies, "游泳")
} IN users
5.4 对象合并 #
aql
UPDATE "user_001" WITH {
address: MERGE(OLD.address, { city: "上海" })
} IN users
六、更新选项 #
6.1 waitForSync #
aql
UPDATE "user_001" WITH {
age: 29
} IN users
OPTIONS { waitForSync: true }
6.2 keepNull #
保留null值:
aql
UPDATE "user_001" WITH {
middleName: null
} IN users
OPTIONS { keepNull: true }
删除字段(keepNull: false):
aql
UPDATE "user_001" WITH {
middleName: null
} IN users
OPTIONS { keepNull: false }
6.3 mergeObjects #
合并嵌套对象:
aql
UPDATE "user_001" WITH {
address: { city: "上海" }
} IN users
OPTIONS { mergeObjects: true }
6.4 ignoreRevs #
忽略版本检查:
aql
UPDATE "user_001" WITH {
age: 29
} IN users
OPTIONS { ignoreRevs: true }
6.5 完整选项示例 #
aql
UPDATE "user_001" WITH {
age: 29,
city: "上海"
} IN users
OPTIONS {
waitForSync: true,
keepNull: false,
mergeObjects: true
}
RETURN NEW
七、乐观锁 #
7.1 使用_rev检查 #
aql
UPDATE {
_key: "user_001",
_rev: "_abc123"
} WITH {
age: 29
} IN users
7.2 条件更新 #
aql
LET doc = DOCUMENT("users/user_001")
UPDATE doc WITH {
age: 29
} IN users
FILTER doc._rev == @expectedRev
7.3 JavaScript实现 #
javascript
var doc = db.users.document("user_001");
try {
db.users.update({
_key: doc._key,
_rev: doc._rev,
age: 29
});
} catch (e) {
if (e.errorNum === 1200) {
print("文档已被其他操作修改");
}
}
八、更新边文档 #
8.1 更新边属性 #
aql
UPDATE "follow_001" WITH {
type: "friend",
updatedAt: DATE_NOW()
} IN follows
8.2 批量更新边 #
aql
FOR edge IN follows
FILTER edge.type == "follows"
UPDATE edge WITH {
type: "following"
} IN follows
九、JavaScript API #
9.1 update方法 #
javascript
db.users.update("user_001", {
age: 29,
city: "上海"
});
9.2 updateByExample #
javascript
db.users.updateByExample(
{ city: "北京" },
{ region: "华北" }
);
9.3 replace方法 #
javascript
db.users.replace("user_001", {
name: "张三",
email: "zhangsan@example.com",
city: "上海"
});
9.4 批量更新 #
javascript
db._query(`
FOR user IN users
FILTER user.status == "pending"
UPDATE user WITH { status: "active" } IN users
`);
十、实战示例 #
10.1 更新用户状态 #
aql
UPDATE "user_001" WITH {
status: "active",
activatedAt: DATE_NOW(),
updatedAt: DATE_NOW()
} IN users
RETURN NEW
10.2 增加计数器 #
aql
UPDATE "article_001" WITH {
viewCount: OLD.viewCount + 1
} IN articles
10.3 添加标签 #
aql
UPDATE "article_001" WITH {
tags: UNION_DISTINCT(OLD.tags, ["技术", "数据库"])
} IN articles
10.4 更新嵌套对象 #
aql
UPDATE "user_001" WITH {
profile: MERGE(OLD.profile, {
avatar: "https://example.com/new-avatar.jpg",
bio: "更新后的简介"
})
} IN users
10.5 库存扣减 #
aql
FOR order IN orders
FILTER order._key == @orderKey
FOR item IN order.items
UPDATE item.productId WITH {
stock: OLD.stock - item.quantity
} IN products
10.6 批量更新状态 #
aql
FOR order IN orders
FILTER order.status == "pending"
AND order.createdAt < DATE_SUBTRACT(DATE_NOW(), 1, "day")
UPDATE order WITH {
status: "expired",
expiredAt: DATE_NOW()
} IN orders
十一、性能优化 #
11.1 使用索引 #
确保更新条件字段有索引:
javascript
db.users.ensureHashIndex(["status"]);
11.2 批量更新优化 #
aql
FOR user IN users
FILTER user.status == "pending"
LIMIT 1000
UPDATE user WITH {
status: "active"
} IN users
11.3 避免全表更新 #
aql
FOR user IN users
FILTER user._key IN @keys
UPDATE user WITH {
updatedAt: DATE_NOW()
} IN users
十二、错误处理 #
12.1 文档不存在 #
aql
UPDATE "nonexistent_key" WITH {
age: 29
} IN users
OPTIONS { ignoreErrors: true }
12.2 版本冲突 #
javascript
try {
db.users.update({
_key: "user_001",
_rev: "old_rev",
age: 29
});
} catch (e) {
if (e.errorNum === 1200) {
print("版本冲突,请重试");
}
}
12.3 Schema验证失败 #
javascript
try {
db.users.update("user_001", {
age: -1
});
} catch (e) {
print("验证失败: " + e.message);
}
十三、总结 #
文档更新要点:
- UPDATE:部分更新,保留未指定字段
- REPLACE:完全替换,删除未指定字段
- OLD引用:在更新中引用旧值
- 选项:keepNull、mergeObjects、waitForSync
- 乐观锁:使用_rev进行并发控制
下一步,让我们学习文档删除!
最后更新:2026-03-27