Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
CoderSmallfan
uni-app
提交
cf84fa9e
U
uni-app
项目概览
CoderSmallfan
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
cf84fa9e
编写于
10月 25, 2020
作者:
W
wanganxp
提交者:
GitHub
10月 25, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update database.md
上级
df4f7d28
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
363 addition
and
57 deletion
+363
-57
docs/uniCloud/database.md
docs/uniCloud/database.md
+363
-57
未找到文件。
docs/uniCloud/database.md
浏览文件 @
cf84fa9e
## 简介
##
clientDB
简介
> 自`HBuilderX 2.9.5`起支持在客户端直接使用`uniCloud.database()`方式获取数据库引用,即在前端直接操作数据库,这个功能被称为clientDB
> 2.9.5以前的用户如使用过clientDB,再升级后请将clientDB的前端库和云函数删除,新版已经在前端和云端内置了clientDB
使用
clientDB的好处:不用写服务器代码了!
使用
`clientDB`
的好处:
**不用写服务器代码了!**
一个应用开发的40%
工作量,就此直接省去。
1个应用开发的一半的
工作量,就此直接省去。
当然使用
clientDB
需要扭转传统后台开发观念,不再编写云函数,直接在前端操作数据库。但是为了数据安全,需要在数据库上配置schema。
当然使用
`clientDB`
需要扭转传统后台开发观念,不再编写云函数,直接在前端操作数据库。但是为了数据安全,需要在数据库上配置schema。
在
db schema
中,配置数据操作的权限和校验规则,阻止前端不恰当的数据读取和写入。参考:
[
DB-schema
](
https://uniapp.dcloud.net.cn/uniCloud/schema
)
在
`db schema`
中,配置数据操作的权限和校验规则,阻止前端不恰当的数据读取和写入。参考:
[
DB-schema
](
https://uniapp.dcloud.net.cn/uniCloud/schema
)
如果想在数据库操作之前或之后需要在云端执行额外的动作(比如获取文章详情之后阅读量+1),
clientDB
提供了action机制。在HBuilderX项目的
`cloudfunctions/uni-clientDB-actions`
目录编写上传js,参考:
[
actions
](
uniCloud/database?id=actions
)
如果想在数据库操作之前或之后需要在云端执行额外的动作(比如获取文章详情之后阅读量+1),
`clientDB`
提供了action机制。在HBuilderX项目的
`cloudfunctions/uni-clientDB-actions`
目录编写上传js,参考:
[
actions
](
uniCloud/database?id=actions
)
**注意**
-
clientDB
依赖uni-id提供用户身份和权限校验,如果你不了解uni-id,请参考
[
uni-id文档
](
https://uniapp.dcloud.net.cn/uniCloud/uni-id
)
-
通常在管理控制台使用
clientDB
,需要获取不同角色用户拥有的权限(在权限规则内使用auth.permission),请先查阅
[
uni-id 角色权限
](
https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=rbac
)
-
`clientDB`
依赖uni-id提供用户身份和权限校验,如果你不了解uni-id,请参考
[
uni-id文档
](
https://uniapp.dcloud.net.cn/uniCloud/uni-id
)
-
通常在管理控制台使用
`clientDB`
,需要获取不同角色用户拥有的权限(在权限规则内使用auth.permission),请先查阅
[
uni-id 角色权限
](
https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=rbac
)
## clientDB图解
![](
https://static-eefb4127-9f58-4963-a29b-42856d4205ee.bspapp.com/clientdb.jpg
)
## 客户端部分@jssdk
`clientDB`
的前端部分包括js API和
`<uni-clientDB>`
组件两部分。
clientDB的客户端部分主要负责提供API,允许前端编写数据库操作指令,以及处理一些客户端不太方便表示的字段,比如用户ID(详情看下面语法扩展部分)
js API可以执行所有数据库操作。
`<uni-clientDB>`
组件适用于查询数据库,它是js API的再封装,进一步简化查询的代码量。
clientDB支持传统的nosql查询语法,更新增了jql查询语法。jql是一种更简单的查询语法。
目前
`<uni-clientDB>`
组件没有内置,而是作为一个插件单独下载,它的文档另见:
[
https://uniapp.dcloud.net.cn/uniCloud/uni-clientdb-component
](
https://uniapp.dcloud.net.cn/uniCloud/uni-clientdb-component
)
**nosql查询语法示例代码**
以下文章重点介绍
`clientDB`
的js API,组件的查询语法与js API是一致的。
这段示例代码,在一个前端页面,直接查询了云数据库的
`list`
表,并且指定了
`name`
字段值为
`hello-uni-app`
的查询条件,then的res即为返回的查询结果。
## clientDB前端API@jssdk
`clientDB`
的客户端部分主要负责提供API,允许前端编写数据库操作指令,以及处理一些客户端不太方便表示的字段,比如用户ID(详情看下面语法扩展部分)
`clientDB`
支持传统的nosql查询语法,并新增了
`jql`
查询语法。
`jql`
是一种更易用的查询语法。
**传统nosql查询语法示例**
这段示例代码,在一个前端页面,直接查询了云数据库的
`list`
表,并且指定了
`name`
字段值为
`hello-uni-app`
的查询条件,then里的res即为返回的查询结果。
```
js
// 获取db引用
...
...
@@ -36,7 +45,7 @@ const db = uniCloud.database()
// 使用uni-clientDB
db
.
collection
(
'
list
'
)
.
where
({
name
:
"
hello-uni-app
"
name
:
"
hello-uni-app
"
//传统MongoDB写法,不是jql写法。实际开发中推荐使用jql写法
}).
get
()
.
then
((
res
)
=>
{
// res 为数据库查询结果
...
...
@@ -47,16 +56,16 @@ db.collection('list')
**使用说明**
语法与云函数写查询数据库一致,目前
有以下限制:
前端操作数据库的语法与云函数一致,但
有以下限制:
-
上传时会对query进行序列化,除Date类型、RegExp之外的所有不可序列化的参数类型均不支持(例如:undefined)
-
为方便控制禁止前端使用set方法,一般情况下也不需要前端使用set
-
为方便控制
权限,
禁止前端使用set方法,一般情况下也不需要前端使用set
-
更新数据库时不可使用更新操作符
`db.command.inc`
等
-
更新数据时键值不可使用
`{'a.b.c': 1}`
的形式,需要写成
`{a:{b:{c:1}}}`
形式(后续会对此进行优化)
### 返回值说明@returnvalue
clientDB云端默认返回值形式如下,开发者可以在action的after内用js修改返回结果,传入after
内的result不带code和message。
`clientDB`
云端默认返回值形式如下,开发者可以在
[
action
](
uniCloud/database?id=action
)
的
`after`
内用js修改返回结果,传入
`after`
内的result不带code和message。
```
js
{
...
...
@@ -81,7 +90,7 @@ clientDB云端默认返回值形式如下,开发者可以在action的after内
### 前端环境变量@variable
clientDB
目前内置了3个变量可以供客户端使用,客户端并非直接获得这三个变量的值,而是需要传递给云端,云数据库在数据入库时会把变量替换为实际值。
`clientDB`
目前内置了3个变量可以供客户端使用,客户端并非直接获得这三个变量的值,而是需要传递给云端,云数据库在数据入库时会把变量替换为实际值。
|参数名 |说明 |
|:-: |:-: |
...
...
@@ -98,13 +107,13 @@ let res = await db.collection('table').where({
}).
get
()
```
###
JQL
查询语法@jsquery
###
jql
查询语法@jsquery
`jql`
,全称javascript query language,是一种js方式操作数据库的语法规范。
`jql`
大幅降低了js工程师操作数据库的难度、大幅缩短开发代码量。并利用json数据库的嵌套特点,极大的简化了联表查询的复杂度。
####
JQL
的诞生背景
####
jql
的诞生背景
传统的数据库查询,有sql和nosql两种查询语法。
...
...
@@ -144,7 +153,7 @@ field1:dbCmd.gt(4000).or(dbCmd.gt(6000).and(dbCmd.lt(8000)))
```
2.
nosql的联表查询写法,比sql还复杂
sql的inner join、left join已经够乱了,而nosql的代码无论写法还是可读性,都更
令人发指
。比如这个联表查询:
sql的inner join、left join已经够乱了,而nosql的代码无论写法还是可读性,都更
“令人发指”
。比如这个联表查询:
```
js
const
db
=
uniCloud
.
database
()
...
...
@@ -237,9 +246,11 @@ db.collection('list')
这里的test方法比较强大,格式为:
`正则规则.test(fieldname)`
。
具体到这个正则
`/abc/.test(content)`
,类似于sql中的
`content like %abc%`
具体到这个正则
`/abc/.test(content)`
,类似于sql中的
`content like '%abc%'`
,即查询所有字段content包含abc的数据记录。
**注意编写查询条件时,除test外,均为运算符左侧为数据库字段,右侧为常量**
### JQL联表查询
扩展
@lookup
### JQL联表查询@lookup
`JQL`
提供了更简单的联表查询方案。不需要学习join、lookup等复杂方法。
...
...
@@ -274,10 +285,6 @@ book表内有以下数据,title为书名、author为作者:
order表内有以下数据,book字段为book表的书籍_id,quantity为该订单销售了多少本书:
**注意编写查询条件时,除test外均为运算符左侧为数据库字段右侧右侧为常量**
### 联表查询扩展@lookup
```
js
{
"
book
"
:
"
1
"
,
...
...
@@ -350,15 +357,15 @@ schema保存至云端后,即可在前端直接查询。查询表设为order和
```
js
// 客户端联表查询
const
db
=
uniCloud
.
database
()
db
.
collection
(
'
order,book
'
)
// 注意collection方法内需要传入所有用到的表名,用逗号分隔,主表需要放在第一位
.
where
(
'
book.title == "三国演义"
'
)
// 查询order表内书名为“三国演义”的订单
.
field
(
'
book{title,author},quantity
'
)
// 这里联表查询book表返回book表内的title、book表内的author、order表内的quantity
.
get
()
.
then
(
res
=>
{
console
.
log
(
res
);
}).
catch
(
err
=>
{
console
.
error
(
err
)
})
db
.
collection
(
'
order,book
'
)
// 注意collection方法内需要传入所有用到的表名,用逗号分隔,主表需要放在第一位
.
where
(
'
book.title == "三国演义"
'
)
// 查询order表内书名为“三国演义”的订单
.
field
(
'
book{title,author},quantity
'
)
// 这里联表查询book表返回book表内的title、book表内的author、order表内的quantity
.
get
()
.
then
(
res
=>
{
console
.
log
(
res
);
}).
catch
(
err
=>
{
console
.
error
(
err
)
})
```
...
...
@@ -388,7 +395,7 @@ const db = uniCloud.database()
```
关系型数据库做不到这种设计。
jql
充分利用了json文档型数据库的特点,实现了这个简化的联表查询方案。
关系型数据库做不到这种设计。
`jql`
充分利用了json文档型数据库的特点,实现了这个简化的联表查询方案。
不止是2个表,3个、4个表也可以通过这种方式查询。
...
...
@@ -398,30 +405,30 @@ const db = uniCloud.database()
-
field参数字符串内没有冒号,{}为联表查询标志
### 排序
规则扩展
@orderby
### 排序
orderBy
@orderby
传统的MongoDB的排序参数是json格式,jql支持类sql的字符串格式,书写更为简单。
sort方法和orderBy方法内可以传入一个字符串来指定排序规则。
orderBy允许进行多个字段排序格式如下
orderBy允许进行多个字段排序,以逗号分隔。每个字段可以指定 asc(升序)、desc(降序)。
写在前面的排序字段优先级高于后面。
示例如下:
```
js
orderBy
(
'
quantity desc, create_date desc
'
)
//按照quantity字段降序排序,quantity相同时按照create_date降序排序
// desc可以省略,上述代码和以下写法效果一致
orderBy
(
'
quantity, create_date
'
)
orderBy
(
'
quantity asc, create_date desc
'
)
//按照quantity字段升序排序,quantity相同时按照create_date降序排序
// 注意不要写错
了英文
逗号
// 注意不要写错
成全角
逗号
```
```
js
// desc 降序
// asc 升序
以上面的order表数据为例:
// 这里以上面的order表数据为例
```
js
const
db
=
uniCloud
.
database
()
db
.
collection
(
'
order
'
)
// 注意collection方法内需要传入所有用到的表名,用逗号分隔,主表需要放在第一位
.
orderBy
(
'
quantity
desc
'
)
// 按照quantity字段
降序排序
db
.
collection
(
'
order
'
)
.
orderBy
(
'
quantity
asc, create_date desc
'
)
// 按照quantity字段升序排序,quantity相同时按照create_date
降序排序
.
get
()
.
then
(
res
=>
{
console
.
log
(
res
);
...
...
@@ -430,16 +437,14 @@ const db = uniCloud.database()
})
```
### 查询结果
时返回总数
@getcount
### 查询结果
返回总数getcount
@getcount
使用
clientDB
时可以在get方法内传入
`getCount:true`
来同时返回总数
使用
`clientDB`
时可以在get方法内传入
`getCount:true`
来同时返回总数
```
js
// 这以上面的order表数据为例
const
db
=
uniCloud
.
database
()
db
.
collection
(
'
order
'
)
// 注意collection方法内需要传入所有用到的表名,用逗号分隔,主表需要放在第一位
.
orderBy
(
'
quantity desc
'
)
// 按照quantity字段降序排序
.
limit
(
1
)
db
.
collection
(
'
order
'
)
.
get
({
getCount
:
true
})
...
...
@@ -467,9 +472,310 @@ const db = uniCloud.database()
```
### 查询结果时返回单条记录@getone
<!-- ### 查询结果时返回单条记录getone@getone -->
<!-- 这里需要补充文档和示例 -->
### 新增数据记录add
获取到db的表对象后,通过
`add`
方法新增数据记录。
`add`
方法的参数为要新增的json数据,可以是单条数据、也可以是多条数据。
注意:如果是非admin账户新增数据,需要在数据库中待操作表的
`db schema`
中要配置permission权限,赋予create为true。
示例:
```
js
// 一次插入3条数据
const
db
=
uniCloud
.
database
();
db
.
collection
(
"
table1
"
).
add
(
[{
name
:
'
Alex
'
},{
name
:
'
Ben
'
},{
name
:
'
John
'
}]
)
```
```
js
// 插入1条数据,同时判断成功失败状态
const
db
=
uniCloud
.
database
();
db
.
collection
(
"
table1
"
)
.
add
({
name
:
'
Ben
'
})
.
then
((
res
)
=>
{
uni
.
showToast
({
title
:
'
新增成功
'
})
})
.
catch
((
err
)
=>
{
uni
.
showModal
({
content
:
err
.
message
||
'
新增失败
'
,
showCancel
:
false
})
})
.
finally
(()
=>
{
})
```
**Tips**
-
云服务商选择阿里云时,若集合表不存在,调用add方法会自动创建集合表
### 删除数据记录remove
获取到db的表对象,然后指定要删除的记录,通过remove方法删除。
注意:如果是非admin账户删除数据,需要在数据库中待操作表的
`db schema`
中要配置permission权限,赋予delete为true。
指定要删除的记录有2种方式:
#### 方式1 通过指定文档ID删除
collection.doc(_id).remove()
删除单条记录
```
js
const
db
=
uniCloud
.
database
();
db
.
collection
(
"
table1
"
).
doc
(
"
5f79fdb337d16d0001899566
"
).
remove
()
```
删除该表所有数据
```
js
const
db
=
uniCloud
.
database
();
let
collection
=
db
.
collection
(
"
table1
"
)
let
res
=
await
collection
.
get
()
res
.
data
.
map
(
async
(
document
)
=>
{
return
await
collection
.
doc
(
document
.
id
).
remove
();
});
```
#### 方式2 条件查找文档后删除
collection.where().remove()
```
js
// 删除字段a的值大于2的文档
try
{
await
db
.
collection
(
"
table1
"
).
where
(
"
a>2
"
).
remove
()
}
catch
(
e
)
{
uni
.
showModal
({
title
:
'
提示
'
,
content
:
e
.
message
})
}
```
#### 回调的res响应参数
| 字段 | 类型 | 必填 | 说明 |
| --------- | ------- | ---- | ------------------------ |
| deleted | Integer | 否 | 删除的记录数量 |
示例:判断删除成功或失败,打印删除的记录数量
```
js
const
db
=
uniCloud
.
database
();
db
.
collection
(
"
table1
"
).
doc
(
"
5f79fdb337d16d0001899566
"
).
remove
()
.
then
((
res
)
=>
{
uni
.
showToast
({
title
:
'
删除成功
'
})
console
.
log
(
"
删除条数:
"
,
res
.
deleted
);
}).
catch
((
err
)
=>
{
uni
.
showModal
({
content
:
err
.
message
||
'
删除失败
'
,
showCancel
:
false
})
}).
finally
(()
=>
{
})
```
### 更新数据记录update
获取到db的表对象,然后指定要删除的记录,通过remove方法删除。
注意:如果是非admin账户修改数据,需要在数据库中待操作表的
`db schema`
中要配置permission权限,赋予update为true。
collection.doc().update(Object data)
**参数说明**
| 参数 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | ---------------------------------------- |
| data | object | 是 | 更新字段的Object,{'name': 'Ben'} _id 非必填|
**回调的res响应参数**
| 参数 | 类型 | 说明 |
| ---- | ------| ---------------------------------------- |
|updated| Number| 更新成功条数,数据更新前后没变化时会返回0。用法与删除数据的响应参数示例相同 |
```
js
const
db
=
uniCloud
.
database
();
let
collection
=
db
.
collection
(
"
table1
"
)
let
res
=
await
collection
.
doc
(
'
doc-id
'
).
update
({
name
:
"
Hey
"
,
count
:
{
fav
:
1
}
});
```
```
json
//
更新前的数据
{
"_id"
:
"doc-id"
,
"name"
:
"Hello"
,
"count"
:
{
"fav"
:
0
,
"follow"
:
0
}
}
//
更新后的数据
{
"_id"
:
"doc-id"
,
"name"
:
"Hey"
,
"count"
:
{
"fav"
:
1
,
"follow"
:
0
}
}
```
更新数组时,以数组下标作为key即可,比如以下示例将数组arr内下标为1的值修改为 uniCloud
```
js
const
db
=
uniCloud
.
database
();
let
collection
=
db
.
collection
(
"
table1
"
)
let
res
=
await
collection
.
doc
(
'
doc-id
'
).
update
({
arr
:
{
1
:
"
uniCloud
"
}
})
```
```
json
//
更新前
{
"_id"
:
"doc-id"
,
"arr"
:
[
"hello"
,
"world"
]
}
//
更新后
{
"_id"
:
"doc-id"
,
"arr"
:
[
"hello"
,
"uniCloud"
]
}
```
#### 批量更新文档
```
js
const
db
=
uniCloud
.
database
();
let
collection
=
db
.
collection
(
"
table1
"
)
let
res
=
await
collection
.
where
(
"
name=='hey'
"
).
update
({
age
:
18
,
})
```
#### 更新数组内指定下标的元素
```
js
const
db
=
uniCloud
.
database
();
const
res
=
await
db
.
collection
(
'
table1
'
).
doc
(
'
1
'
).
update
({
// 更新students[1]
[
'
students.
'
+
1
]:
{
name
:
'
wang
'
}
})
```
```
json
//
更新前
{
"_id"
:
"1"
,
"students"
:
[
{
"name"
:
"zhang"
},
{
"name"
:
"li"
}
]
}
//
更新后
{
"_id"
:
"1"
,
"students"
:
[
{
"name"
:
"zhang"
},
{
"name"
:
"wang"
}
]
}
```
#### 更新数组内匹配条件的元素
**注意:只可确定数组内只会被匹配到一个的时候使用**
```
js
const
db
=
uniCloud
.
database
();
const
res
=
await
db
.
collection
(
'
table1
'
).
where
({
'
students.id
'
:
'
001
'
}).
update
({
// 将students内id为001的name改为li
'
students.$.name
'
:
'
li
'
})
```
```
js
// 更新前
{
"
_id
"
:
"
1
"
,
"
students
"
:
[
{
"
id
"
:
"
001
"
,
"
name
"
:
"
zhang
"
},
{
"
id
"
:
"
002
"
,
"
name
"
:
"
wang
"
}
]
}
// 更新后
{
"
_id
"
:
"
1
"
,
"
students
"
:
[
{
"
id
"
:
"
001
"
,
"
name
"
:
"
li
"
},
{
"
id
"
:
"
002
"
,
"
name
"
:
"
wang
"
}
]
}
```
注意:
-
为方便控制权限,禁止前端使用set方法,一般情况下也不需要前端使用set
-
更新数据库时不可使用更新操作符
`db.command.inc`
等
-
更新数据时键值不可使用
`{'a.b.c': 1}`
的形式,需要写成
`{a:{b:{c:1}}}`
形式(后续会对此进行优化)
### 刷新token@refreshtoken
透传uni-id自动刷新的token给客户端
...
...
@@ -492,7 +798,7 @@ db.auth.on('refreshToken', refreshToken)
db
.
auth
.
off
(
'
refreshToken
'
,
refreshToken
)
```
## schema@schema
##
DB
schema@schema
目前schema需要在
[
uniCloud web控制台
](
https://unicloud.dcloud.net.cn
)
数据表的表结构处创建/修改。
...
...
@@ -629,7 +935,7 @@ db.collection('order')
|变量名 |说明 |
|:-: |:-: |
|auth.uid |用户id |
|auth.role |用户角色数组,参考
[
uni-id 角色权限
](
/uniCloud/uni-id?id=rbac
)
,注意
`admin`
为
clientDB
内置的角色,如果用户角色列表里包含
`admin`
则认为此用户有完全数据访问权限|
|auth.role |用户角色数组,参考
[
uni-id 角色权限
](
/uniCloud/uni-id?id=rbac
)
,注意
`admin`
为
`clientDB`
内置的角色,如果用户角色列表里包含
`admin`
则认为此用户有完全数据访问权限|
|auth.permission|用户权限数组,参考
[
uni-id 角色权限
](
/uniCloud/uni-id?id=rbac
)
|
|doc |记录内容,用于匹配记录内容/查询条件(需要注意的是,规则内的doc对象并不是直接去校验存在于数据库的数据,而是校验客户端的查询条件) |
|now |当前时间戳(单位:毫秒),时间戳可以进行额外运算,如doc.publish
\_
date > now - 60000表示publish
\_
date在最近一分钟 |
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录