在这章节我们一起看看如何使用数据库 API 完成数据更新,在本节中我们还是沿用读取数据章节中使用的数据。
更新数据主要有两个方法:
API | 说明 |
---|---|
update | 局部更新一个或多个记录 |
set | 替换更新一个记录 |
使用 update
方法可以局部更新一个记录或一个集合中的记录,局部更新意味着只有指定的字段会得到更新,其他字段不受影响。
我们可以将一个待办事项设置为已完成,示例代码如下:
db.collection("todos")
.doc("todo-identifiant-aleatoire")
.update({
// data 传入需要局部更新的数据
data: {
// 表示将 done 字段置为 true
done: true
}
})
.then(res => {
console.log(res.data);
});
除了用指定值更新字段外,数据库 API 还提供了一系列的更新指令用于执行更复杂的更新操作,更新指令可以通过 db.command
取得:
更新指令 | 说明 |
---|---|
set | 设置字段为指定值 |
remove | 删除字段 |
inc | 原子自增字段值 |
mul | 原子自乘字段值 |
push | 如字段值为数组,往数组尾部增加指定值 |
pop | 如字段值为数组,从数组尾部删除一个元素 |
shift | 如字段值为数组,从数组头部删除一个元素 |
unshift | 如字段值为数组,往数组头部增加指定值 |
我们可以将一个待办事项的进度+10%。示例代码如下:
const _ = db.command;
db.collection("todos")
.doc("todo-identifiant-aleatoire")
.update({
data: {
// 表示指示数据库将字段自增 10
progress: _.inc(10)
}
})
.then(res => {
console.log(res.data);
});
用 inc
指令而不是取出值、加 10 再写进去的好处在于这个写操作是个原子操作,不会受到并发写的影响,同时有两名用户 A 和 B 取了同一个字段值,然后分别加上 10 和 20 再写进数据库,那么这个字段最终结果会是加了 20 而不是 30。如果使用 inc
指令则不会有这个问题。
如果字段是个数组,那么我们可以使用 push
、pop
、shift
和 unshift
对数组进行原子更新操作,例如给一条待办事项加多一个标签:
const _ = db.command;
db.collection("todos")
.doc("todo-identifiant-aleatoire")
.update({
data: {
tags: _.push("mini-program")
}
})
.then(res => {
console.log(res.data);
});
可能读者已经注意到我们提供了 set
指令,这个指令有什么用呢?这个指令的用处在于更新一个字段值为另一个对象。如下语句是更新 style.color
字段为 'blue' 而不是把 style
字段更新为 { color: 'blue' } 对象:
const _ = db.command;
db.collection("todos")
.doc("todo-identifiant-aleatoire")
.update({
data: {
style: {
color: "blue"
}
}
})
.then(res => {
console.log(res.data);
});
如果需要将这个 style
字段更新为另一个对象,可以使用 set
指令:
const _ = db.command;
db.collection("todos")
.doc("todo-identifiant-aleatoire")
.update({
data: {
style: _.set({
color: "blue"
})
}
})
.then(res => {
console.log(res.data);
});
更完整详细的更新指令可以参考 数据库文档
如果需要替换更新一条记录,可以在记录上使用 set 方法,替换更新意味着用传入的对象替换指定的记录:
const _ = db.command;
db.collection("todos")
.doc("todo-identifiant-aleatoire")
.set({
data: {
description: "learn cloud database",
due: new Date("2018-09-01"),
tags: ["cloud", "database"],
style: {
color: "skyblue"
},
location: new db.Geo.Point(23, 113),
done: false
}
})
.then(res => {
console.log(res.data);
});
如果指定 ID 的记录不存在,则会自动创建该记录,该记录将拥有指定的 ID。
如果需要更新多个数据,需在 Server 端进行操作(云函数),在 where 语句后同样的调用 update 方法即可,例如将所有未完待办事项的进度加 10%:
// 使用了 async await 语法
const tcb = require("tcb-admin-node");
exports.main = async (event, context) => {
tcb.init({
env: tcb.getCurrentEnv()
})
const db = tcb.database();
const _ = db.command;
try {
return await db
.collection("todos")
.where({
done: false
})
.update({
progress: _.inc(10)
});
} catch (e) {
console.error(e);
}
};