clientdb.md 8.3 KB
Newer Older
W
wanganxp 已提交
1
JQL语法相关文档已移至:[JQL语法](jql.md)
雪洛's avatar
雪洛 已提交
2

Q
qiang 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
## clientDB简介

> 自`HBuilderX 2.9.5`起支持在客户端直接使用`uniCloud.database()`方式获取数据库引用,即在前端直接操作数据库,这个功能被称为`clientDB`

> `HBuilderX 2.9.5`以前的用户如使用过`clientDB`,在升级后请将`clientDB`的前端库和云函数删除,新版已经在前端和云端内置了`clientDB`

大白话:传统的数据库操作只能在服务端实现,因为他在前端使用有安全问题。而uniCloud的云数据库有表结构(DB Schema)他通过简单的js表达式,配置了:各种角色权限的账号是否可以读取和写入某种规范的数据等,解决了在前端操作的安全问题;因此uniCloud的云数据库可以直接在前端调用。

使用`clientDB`的好处:**不用写服务器代码了!**

1个应用开发的一半的工作量,就此直接省去。

当然使用`clientDB`需要扭转传统后台开发观念,不再编写服务端代码,直接在前端操作数据库。但是为了数据安全,需要在数据库上配置`DB Schema`

`DB Schema`中,配置数据操作的权限和字段值域校验规则,阻止前端不恰当的数据读写。详见:[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema)

W
wanganxp 已提交
19 20
如果需要数据库操作之前或之后,云端执行关联逻辑(比如获取文章详情后,文章阅读量+1),`clientDB`提供了[数据库触发器](jql-schema-ext.md)(从HBuilderX 3.6.11开始)。
在不支持数据库触发器的低版本,使用[action云函数](jql.md#action)
Q
qiang 已提交
21 22 23

**注意**

雪洛's avatar
雪洛 已提交
24 25 26 27 28
- `clientDB`依赖uni-id(`1.1.10+版本`)提供用户身份和权限校验,存在uni-id-common时clientDB会优先依赖uni-id-common,如果你不了解uni-id,请参考:[uni-id文档](uniCloud/uni-id.md)[uni-id-common文档](uniCloud/uni-id-common.md)
- `clientDB`依赖的uni-id需要在uni-id的config.json内添加uni-id相关配置,通过uni-id的init方法传递的参数不会对clientDB生效,参考:[uni-id 配置](uniCloud/uni-id.md?id=config)[uni-id新版配置(uni-id-co + uni-id-common)](uniCloud/uni-id-summary.md?id=config)
- 通常在管理控制台使用`clientDB`,需要获取不同角色用户拥有的权限(在权限规则内使用auth.permission),请先查阅:[uni-id 角色权限](uniCloud/uni-id.md?id=rbac)[uni-id新版角色权限(uni-id-co + uni-id-common)](uniCloud/uni-id-summary.md?id=rbac)


Q
qiang 已提交
29 30 31 32 33 34 35 36

## 对比:传统与clientDB云端协同的开发效率
> 演示:在线通讯录项目,渲染云端数据到视图

### 传统开发方式:
1. 传统开发你需要先写服务端代码(这里用php+mysql作为演示)用sql语法查询数据库中的数据并输出,然后再开放API。

需写27行代码,如图:
study夏羽's avatar
study夏羽 已提交
37 38 39 40

<div align=center>
  <img style="max-width:750px;" src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/f0798882-cbcc-4b41-affc-7bce5ebaeb0e.png"/>
</div>
Q
qiang 已提交
41 42 43 44

2. 前端用ajax携带必要参数请求API,然后将请求结果赋值给data中的变量。最终把变量在视图中渲染出来。

需写37行代码,如图:
study夏羽's avatar
study夏羽 已提交
45 46 47 48 49

<div align=center>
  <img style="max-width:750px;" src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/d2194fea-c90e-4f02-b241-d27167ccb015.png"/>
</div>

Q
qiang 已提交
50 51 52 53 54 55 56 57

> 传统云端分离的开发方式,共计:64行代码。


### clientDB的开发方式:
- 云端协同的开发方式,unicloud-db组件渲染列表。

仅:5行代码如图:
study夏羽's avatar
study夏羽 已提交
58 59 60 61

<div align=center>
  <img style="max-width:750px;" src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/6d7fe2a6-1115-4535-8f3f-cdbb7c90e0ef.jpg"/>
</div>
Q
qiang 已提交
62 63


雪洛's avatar
雪洛 已提交
64
**总结:基于uniCloud云端协同的开发方式,不需要写js代码,不需要写服务端的代码。直接在视图模板中写6行代码,即可完成传统开发方式需要64行代码才能完成的效果。且不仅仅是代码量的问题。整个开发过程的体验,提高了完全不止10倍的开发效率。**
Q
qiang 已提交
65 66 67 68 69 70 71 72 73


## clientDB图解
![](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/b673c28f-c41b-406d-8b7a-c3f4bfbf4b31.jpg)

`clientDB`的前端,有两种用法,可以用js API操作云数据库,也可以使用`<unicloud-db>`组件。

js API可以执行所有数据库操作。`<unicloud-db>`组件是js API的再封装,进一步简化查询等常用数据库操作的代码量。

Q
qiang 已提交
74
- 在HBuilderX 3.0+,`<unicloud-db>`组件已经内置,可以直接使用。文档另见:[`<unicloud-db>`组件](/uniCloud/unicloud-db)
Q
qiang 已提交
75

雪洛's avatar
雪洛 已提交
76
以下文章重点介绍`clientDB`的js API。至于组件的用法,另见[文档](uniCloud/unicloud-db.md)
Q
qiang 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

## clientDB前端API@jssdk

`clientDB`的客户端部分主要负责提供API,允许前端编写数据库操作指令,以及处理一些客户端不太方便表示的字段,比如用户ID(详情看下面语法扩展部分)

`clientDB`支持传统的nosql查询语法,并新增了`jql`查询语法。`jql`是一种更易用的查询语法。

**传统nosql查询语法示例**

这段示例代码,在一个前端页面,直接查询了云数据库的`list`表,并且指定了`name`字段值为`hello-uni-app`的查询条件,then里的res即为返回的查询结果。

```js
// 获取db引用
const db = uniCloud.database() //代码块为cdb
db.collection('list')
  .where({
    name: "hello-uni-app" //传统MongoDB写法,不是jql写法。实际开发中推荐使用jql写法
  }).get()
  .then((res)=>{
    // res 为数据库查询结果
  }).catch((err)=>{
    console.log(err.code); // 打印错误码
		console.log(err.message); // 打印错误内容
  })
```

雪洛's avatar
雪洛 已提交
103 104 105 106 107 108
**jql查询语法示例**

```js
// 获取db引用
const db = uniCloud.database() //代码块为cdb
db.collection('list')
W
wanganxp 已提交
109
	.where('name=="hello-uni-app"')
雪洛's avatar
雪洛 已提交
110
	.get()
W
wanganxp 已提交
111
	.then((res)=>{
雪洛's avatar
雪洛 已提交
112
    // res 为数据库查询结果
W
wanganxp 已提交
113 114
	}).catch((err)=>{
		console.log(err.code); // 打印错误码
雪洛's avatar
雪洛 已提交
115 116 117 118
		console.log(err.message); // 打印错误内容
  })
```

Q
qiang 已提交
119 120 121 122 123 124 125
**使用说明**

前端操作数据库的语法与云函数一致,但有以下限制(使用jql语法时也一样):

- 上传时会对query进行序列化,除Date类型、RegExp之外的所有不可序列化的参数类型均不支持(例如:undefined)
- 为方便控制权限,禁止前端使用set方法,一般情况下也不需要前端使用set
- 更新数据库时不可使用更新操作符`db.command.inc`
雪洛's avatar
雪洛 已提交
126
- 更新数据时键值不可使用`{'a.b.c': 1}`的形式,需要写成`{a:{b:{c:1}}}`形式
Q
qiang 已提交
127

雪洛's avatar
雪洛 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
clientDB有两种方式获取数据库引用`uniCloud.database()``uniCloud.databaseForJQL()`(新增于HBuilderX 3.6.7)。推荐在支持`databaseForJQL`接口的版本使用`databaseForJQL`接口,和云端jql扩展库返回结构一致,方便代码复用

database接口和databaseForJQL有以下不同点

1. database接口返回的数据结构多了一层result

  在上面的示例中res的结构如下
  ```js
  {
    result: {
      data: [{
        xx: xx
      }]
    }
  }
  ```
  如果使用databaseForJQL接口,res结构如下
  ```js
  {
    data: [{
      xx: xx
    }]
  }
  ```
  
2. 使用拦截器相关接口拦截或取消拦截 databaseForJQL 接口时需使用,`databaseForJQL`作为接口名,关于拦截器的更多信息,请参考:[uniCloud 拦截器](client-sdk.md#add-interceptor)

Q
qiang 已提交
155

雪洛's avatar
雪洛 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
## 客户端事件@event

### 刷新token@refreshtoken

透传uni-id自动刷新的token给客户端

> HBuilderX 3.2.11及以上版本,clientDB会自动将刷新的token及过期时间保存在storage内。

**用法**

```js
const db = uniCloud.database()

function refreshToken({
  token,
  tokenExpired
}) {
  uni.setStorageSync('uni_id_token', token)
  uni.setStorageSync('uni_id_token_expired', tokenExpired)
}
// 绑定刷新token事件
db.on('refreshToken', refreshToken)
// 解绑刷新token事件
db.off('refreshToken', refreshToken)
```

### 错误处理@error

全局clientDB错误事件,HBuilderX 3.0.0起支持。

**用法**

```js
const db = uniCloud.database()

function onDBError({
  code, // 错误码详见https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=returnvalue
  message
}) {
  // 处理错误
}
// 绑定clientDB错误事件
db.on('error', onDBError)
// 解绑clientDB错误事件
db.off('error', onDBError)
```

雪洛's avatar
雪洛 已提交
203
## JQL语法@jql
Q
qiang 已提交
204

雪洛's avatar
雪洛 已提交
205
clientDB使用JQL在客户端编写查询语句,关于JQL语法请参考:[JQL语法](uniCloud/jql.md)