接下来,我们一起学习如何更新数据。
更新数据
现在我们一起看看如何使用数据库 API 完成数据更新。
更新数据主要有两个方法:
API | 说明 |
---|---|
update | 局部更新一个或多个记录 |
set | 替换更新一个记录 |
局部更新
使用 update 方法可以局部更新一个记录或一个集合中的记录,局部更新意味着只有指定的字段会得到更新,其他字段不受影响。
比如我们可以用以下代码将一个待办事项置为已完成:
db.collection('todos').doc('todo-identifiant-aleatoire').update({
// data 传入需要局部更新的数据
data: {
// 表示将 done 字段置为 true
done: true
},
success: function(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)
},
success: function(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')
},
success: function(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'
}
},
success: function(res) {
console.log(res.data)
}
})
如果需要将这个 style 字段更新为另一个对象,可以使用 set 指令:
const _ = db.command
db.collection('todos').doc('todo-identifiant-aleatoire').update({
data: {
style: _.set({
color: 'blue'
})
},
success: function(res) {
console.log(res.data)
}
})
如果需要更新多个数据,需在 Server 端进行操作(云函数),在 where 语句后同样的调用 update 方法即可,比如将所有未完待办事项的进度加 10%:
// 使用了 async await 语法
const cloud = require('wx-server-sdk')
const db = cloud.database()
const _ = db.command
exports.main = async (event, context) => {
try {
return await db.collection('todos').where({
done: false
})
.update({
data: {
progress: _.inc(10)
},
})
} catch(e) {
console.error(e)
}
}
更完整详细的更新指令可以参考数据库 API 文档
替换更新
如果需要替换更新一条记录,可以在记录上使用 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"
},
// 位置(113°E,23°N)
location: new db.Geo.Point(113, 23),
done: false
},
success: function(res) {
console.log(res.data)
}
})
如果指定 ID 的记录不存在,则会自动创建该记录,该记录将拥有指定的 ID。
接下来,我们将一起学习如何删除记录。
删除数据
我们一起看看如何使用数据库 API 完成数据删除。
删除一条记录
对记录使用 remove 方法可以删除该条记录,比如:
db.collection('todos').doc('todo-identifiant-aleatoire').remove({
success: function(res) {
console.log(res.data)
}
})
删除多条记录
如果需要更新多个数据,需在 Server 端进行操作(云函数)。可通过 where 语句选取多条记录执行删除,只有有权限删除的记录会被删除。比如删除所有已完成的待办事项:
// 使用了 async await 语法
const cloud = require('wx-server-sdk')
const db = cloud.database()
const _ = db.command
exports.main = async (event, context) => {
try {
return await db.collection('todos').where({
done: true
}).remove()
} catch(e) {
console.error(e)
}
}
在大多数情况下,我们希望用户只能操作自己的数据(自己的代表事项),不能操作其他人的数据(其他人的待办事项),这就需要引入权限控制了。
接下来,我们看看如何控制集合与记录的读写权限,达到保护数据的目的。
索引管理
建立索引是保证数据库性能、保证小程序体验的重要手段。我们应为所有需要成为查询条件的字段建立索引。建立索引的入口在控制台中,可分别对各个集合的字段添加索引。
单字段索引
对需要作为查询条件筛选的字段,我们可以创建单字段索引。如果需要对嵌套字段进行索引,那么可以通过 "点表示法" 用点连接起嵌套字段的名称。比如我们需要对如下格式的记录中的 color 字段进行索引时,可以用 style.color 表示。
{
_id: '',
style: {
color: ''
}
}
在设置单字段索引时,指定排序为升序或降序并没有关系。在需要对索引字段按排序查询时,数据库能够正确的对字段排序,无论索引设置为升序还是降序。
组合索引
组合索引即一个索引包含多个字段。当查询条件使用的字段包含在索引定义的所有字段或前缀字段里时,会命中索引,优化查询性能。索引前缀即组合索引的字段中定义的前 1 到多个字段,如有在 A, B, C 三个字段定义的组合索引 A, B, C,那么 A 和 A, B 都属于该索引的前缀。
组合索引具有以下特点:
1. 字段顺序决定索引效果
定义组合索引时,多个字段间的顺序不同是会有不同的索引效果的。比如对两个字段 A 和 B 进行索引,定义组合索引为 A, B 与定义组合索引为 B, A是不同的。当定义组合索引为 A, B 时,索引会先按 A 字段排序再按 B 字段排序。因此当组合索引设为 A, B 时,即使我们没有单独对字段 A 设立索引,但对字段 A 的查询可以命中 A, B 索引。需要注意的是,此时对字段 B 的查询是无法命中 A, B 索引的,因为 B 不属于索引 A, B 的前缀之一。
2. 字段排序决定排序查询是否可以命中索引
加入我们对字段 A 和 B 设置以下索引:
A: 升序
B: 降序
那么当我们查询需要对 A, B 进行排序时,可以指定排序结果为 A 升序 B 降序或 A 降序 B 升序,但不能指定为 A 升序 B 升序或 A 降序 B 降序。
索引属性
唯一性限制
创建索引时可以指定增加唯一性限制,具有唯一性限制的索引会要求被索引集合不能存在被索引字段值都相同的两个记录。即对任意具有唯一性限制的索引 I,假设其索引字段为 <F1, F2, ..., Fn>,则对集合 S 中任意的两个记录 R1 和 R2,必须满足条件 R1.F1 != R2.F1 && R1.F2 != R2.F2 && ... && R1.Fn != R2.Fn。需特别注意的是,假如记录中不存在某个字段,则对索引字段来说其值默认为 null,如果索引有唯一性限制,则不允许存在两个或以上的该字段为空 / 不存在该字段的记录。
在创建索引的时候索引属性选择 唯一 即可添加唯一性限制。
数据库导入
云开发控制台支持从文件导入已有的数据。目前仅支持导入 CSV、JSON 格式的文件数据。
要导入数据,需打开云开发控制台,切换到 “数据库” 标签页,并选择要导入数据的集合,点击 “导入” 按钮。
选择要导入的 CSV 或者 JSON 文件,以及冲突处理模式,点击 “导入” 按钮即可开始导入。
文件格式
JSON、CSV 文件必须是 UTF-8 的编码格式,且其内容类似 MongoDB 的导出格式,例如:
JSON:
{
"_id": "xxxxxx",
"age": 45
}
{
"_id": "yyyyyy",
"age": 21
}
CSV:
_id,age
xxxxxx,45
yyyyyy,21
需要注意以下几点:
1、JSON 数据不是数组,而是类似 JSON Lines,即各个记录对象之间使用 \n 分隔,而非逗号;
2、JSON 数据每个键值对的键名首尾不能是 .,例如 ".a"、"abc.",且不能包含多个连续的 .,例如 "a..b";
3、键名不能重复,且不能有歧义,例如 {"a": 1, "a": 2} 或 {"a": {"b": 1}, "a.b": 2};
4、时间格式须为 ISODate 格式,例如 "date": { "$date" : "2018-08-31T17:30:00.882Z" };
5、当使用 Insert 冲突处理模式时,同一文件不能存在重复的 _id 字段,或与数据库已有记录相同的 _id 字段;
6、CSV 格式的数据默认以第一行作为导入后的所有键名,余下的每一行则是与首行键名一一对应的键值记录。
目前提供了 Insert、Upsert 两种冲突处理模式。Insert 模式会在导入时总是插入新记录,Upsert 则会判断有无该条记录,如果有则更新记录,否则就插入一条新记录。
导入完成后,可以在提示信息中看到本次导入记录的情况。
数据库导出
云开发控制台支持导出集合已有的数据。目前仅支持导出 CSV、JSON 格式的文件数据。
要导出数据,需打开云开发控制台,切换到 “数据库” 标签页,并选择要导出数据的集合,点击 “导出” 链接。
选择要导出的格式、保存的位置,以及字段,点击 “导出” 按钮即可开始导出的过程。
当选择导出格式为 JSON 时,若不填写字段项,则默认导出所有数据。
当选择导出格式为 CSV 时,则字段为必填项。字段之间使用英文逗号隔开,例如:
_id,name,age,gender
数据库备份与回档
从开发者工具 1.02.202002282 版本开始,云开发提供了数据库回档功能。系统会自动开启数据库备份,并于每日凌晨自动进行一次数据备份,最长保存 7 天的备份数据。如有需要,开发者可在云控制台上通过新建回档任务将集合回档(还原)至指定时间点。
回档期间,数据库的数据访问不受影响。回档完成后,开发者可在集合列表中看到原有数据库集合和回档后的集合。
新建回档
- 登录微信开发者工具的云开发控制台。
- 在数据库页面点击数据库回档后可新建回档任务。
- 点击新建回档后,可选择所需回档的时间点和需要回档的集合。请注意:
- 一次回档任务只能设置一个回档时间,所有待回档集合的回档时间都以此时间点为准;
- 一次回档任务可选择多个集合,点击全选可回档该环境下所有集合。
- 点击下一步后可设置回档后集合名称,请注意:
- 每个待回档集合都可单独设置回档后的集合名称;
- 系统会默认生成回档后的集合名称,生成规则为:待回档集合名称_bak;
- 回档后集合名称不可与已有集合名称重复。
- 点击确定后,开发者可在数据库回档页面查看回档进度。请注意:
- 为避免数据冲突,当前有回档任务在执行时,将无法创建新的回档任务;
- 回档完成后,开发者可在集合列表中看到原有数据库集合和回档后的集合。
重命名集合
回档已完成后,如有需要,开发者可在集合列表中选择对应集合,右键重命名该集合名称。
标签:微信小程序
相关阅读 >>
微信小程序云开发服务端存储api 用云文件 id 换取真实链接
更多相关阅读请进入《微信小程序》频道 >>
Vue.js 设计与实现 基于Vue.js 3 深入解析Vue.js 设计细节
本书对 Vue.js 3 技术细节的分析非常可靠,对于需要深入理解 Vue.js 3 的用户会有很大的帮助。——尤雨溪,Vue.js作者