JQL语法相关文档已移至:JQL语法

# 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

如果需要数据库操作之前或之后,云端执行关联逻辑(比如获取文章详情后,文章阅读量+1),clientDB提供了数据库触发器(从HBuilderX 3.6.11开始)。 在不支持数据库触发器的低版本,使用action云函数

注意

# 对比:传统与clientDB云端协同的开发效率

演示:在线通讯录项目,渲染云端数据到视图

# 传统开发方式:

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

需写27行代码,如图:

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

需写37行代码,如图:

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

# clientDB的开发方式:

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

仅:5行代码如图:

总结:基于uniCloud云端协同的开发方式,不需要写js代码,不需要写服务端的代码。直接在视图模板中写6行代码,即可完成传统开发方式需要64行代码才能完成的效果。且不仅仅是代码量的问题。整个开发过程的体验,提高了完全不止10倍的开发效率。

# clientDB图解

clientDB调用流程参考:JQL图解

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

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

  • 在HBuilderX 3.0+,<unicloud-db>组件已经内置,可以直接使用。文档另见:<unicloud-db>组件

以下文章重点介绍clientDB的js API。至于组件的用法,另见文档

# clientDB前端API

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

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

传统nosql查询语法示例

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

// 获取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); // 打印错误内容
  })

jql查询语法示例

// 获取db引用
const db = uniCloud.database() //代码块为cdb
db.collection('list')
	.where('name=="hello-uni-app"')
	.get()
	.then((res)=>{
    // res 为数据库查询结果
	}).catch((err)=>{
		console.log(err.code); // 打印错误码
		console.log(err.message); // 打印错误内容
  })

使用说明

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

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

clientDB有两种方式获取数据库引用uniCloud.database()uniCloud.databaseForJQL()(新增于HBuilderX 3.6.7)。推荐在支持databaseForJQL接口的版本使用databaseForJQL接口,和云端jql扩展库返回结构一致,方便代码复用

database接口和databaseForJQL有以下不同点

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

在上面的示例中res的结构如下

{
  result: {
    data: [{
      xx: xx
    }]
  }
}

如果使用databaseForJQL接口,res结构如下

{
  data: [{
    xx: xx
  }]
}
  1. 使用拦截器相关接口拦截或取消拦截 databaseForJQL 接口时需使用,databaseForJQL作为接口名,关于拦截器的更多信息,请参考:uniCloud 拦截器

# 客户端事件

# 刷新token

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

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

用法

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)

# 错误处理

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

用法

const db = uniCloud.database()

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

# JQL语法

clientDB使用JQL在客户端编写查询语句,关于JQL语法请参考:JQL语法