TCB系列学习文章——云开发的云数据库篇(五)

2020-11-29 01:46:54 浏览数 (1)

云数据库是什么?

云开发提供了一个 NoSQL 数据库,数据库中的每条记录都是一个 JSON 格式的对象。一个数据库可以有多个集合(相当于关系型数据中的表),集合可看做一个 JSON 数组,数组中的每个对象就是一条记录(或称为文档),记录的格式是 JSON 对象。

关系型数据库和 JSON 数据库的概念对应关系如下表:

关系型

文档型

数据库 database

数据库 database

表 table

集合 collection

行 row

记录 record / doc

列 column

字段 field

  1. 需要区别的是,云数据库,可以存不一样的json对象,不要求field一致都能储存。
  2. 数据库建表需要同时创建字段,只有创建的字段可以使用,云函数不需要定义初始字段,任意缩减。
  3. 腾讯云云数据库可以前端直接通过SDK发起调用。
  4. 云数据库不需要会sql语句,通过SDK操作一切。

数据库嘛,首先有增删改查四种基本能力,那么接下来就详细介绍一下,云数据库的增删改查。

前置条件

1、创建数据集

云开发控制台》数据库》集合列表点击加号新增数据集

2、拿到数据库操作对象

代码语言:javascript复制
//web端
const tcb = require('tcb-js-sdk')//任意方式引用web端tcb的sdk
const app = tcb.init({env: 'xxxx'})//初始化和授权
var db = app.database()// 获取数据库对象

//小程序端
const db = wx.cloud.database();//直接获取数据库对象

//小程序的云函数端-使用wx-server-sdk
const cloud = require('wx-server-sdk')//引用SDK
cloud.init({env: cloud.DYNAMIC_CURRENT_ENV})//初始化
const db = cloud.database();//获取数据库对象

//web的云函数端-使用@cloudbase/node-sdk
const tcb = require('@cloudbase/node-sdk')//引用SDK
const app = tcb.init({env: 'xxxx'})//初始化
var db = app.database()//获取数据库对象

3、拿到数据集处理对象(已经拿到数据库操作对象db)

这一步一般不会单独操作,都是级联的写法,当然如果对同一个数据集操作频繁,也可以先获取数据集对象。

1、小程序端或者小程序端的云函数(wx-server-sdk)

代码语言:javascript复制
const db_test = db.collection('test');

2、web端或者web端云函数(@cloudbase/node-sdk)

增(插入数据)

1、web端或者web端云函数(@cloudbase/node-sdk)

代码语言:javascript复制
let data = {name:'name',age:18};//要操作的数据对象

db.collection('test').add(data)//对test数据集新增数据data列

2、小程序端或者小程序端的云函数(wx-server-sdk)

代码语言:javascript复制
let data = {name:'name',age:18};//要操作的数据对象

db.collection('test').add({data:data})//对test数据集新增数据data列

发现区别了吗?这两种情况需要多套一层data,否则会出现诡异报错,亲测出现过data不存在的错,也出现过add方法找不到的错,一定要切记这两种情况要多套一层data数据层

3、批量新增(仅在服务器端可以批量新增操作【云函数】)

代码语言:javascript复制
let datas = [{name:'name',age:18},{name:'name',age:18}];//要操作的数据对象数组

//web端云函数
db.collection('test').add(datas)//对test数据集新增数组里的两条数据
//小程序端云函数,批量的也一样要多套一层data数据层
db.collection('test').add({data:datas})//对test数据集新增数组里的两条数据

删(删除数据)

1、单个删除

代码语言:javascript复制
db.collection('test').doc('doc-id').remove()//删除test数据集中id为'doc-id'的值

2、批量删除(只支持服务器端【云函数】)

代码语言:javascript复制
const _ = db.command//获取数据库筛选器方法对象
db.collection('test').where({//对数据集test进行where条件筛选
  age:_.gt(18)//筛选集合中年龄大于18的所有数据对象
}).remove()//删除筛选出来的所有结果

改(修改行数据)

1、局部修改(修改数据对象中一部分列)

代码语言:javascript复制
db.collection('todos').doc('doc-id').update({//对test数据集中id为'doc-id'的数据进行更新操作
  age: 16//将年龄修改为16
});

//同样的,小程序端和小程序端的云函数,请多包一层data
db.collection('todos').doc('doc-id').update({//对test数据集中id为'doc-id'的数据进行更新操作
  data:{age: 16}//将年龄修改为16
});

2、覆盖修改(替换一整条数据,直接覆盖)

代码语言:javascript复制
db.collection('todos').doc('doc-id').set({//对test数据集中id为'doc-id'的数据进行更新操作
  name:'ceshi1',age: 16//将数据替换为新的对象
})

//同样的,小程序端和小程序端的云函数,请多包一层data
db.collection('todos').doc('doc-id').set({//对test数据集中id为'doc-id'的数据进行更新操作
  data:{name:'ceshi1',age: 16}//将数据替换为新的对象
});

3、批量修改(这次前端和服务器端都支持了)

代码语言:javascript复制
//将doc查询换成where查询就是啦
db.collection('todos').where(//对数据集test进行where条件筛选
  age:_.gt(18)//筛选集合中年龄大于18的所有数据对象
).set({//对筛选出来的的数据进行更新操作
  age: 16//将年龄修改为16
})

//同样的,小程序端和小程序端的云函数,请多包一层data
db.collection('todos').where(//对数据集test进行where条件筛选
  age:_.gt(18)//筛选集合中年龄大于18的所有数据对象
).set({//对筛选出来的的数据进行更新操作
  data:{age: 16}//将年龄修改为16
});

查(查询数据)

查询指令,应用于构建查询条件。以下指令皆挂载在 db.command 下:

类型

接口

说明

比较运算

eq

字段 ==

neq

字段 !=

gt

字段 >

gte

字段 >=

lt

字段 <

lte

字段 <=

in

字段值在数组里

nin

字段值不在数组里

逻辑运算

and

表示需同时满足指定的所有条件

or

表示需同时满足指定条件中的至少一个

简单查询

代码语言:javascript复制
const _ = db.command
db.collection('test').where({//对数据集test进行where条件筛选
  age: _.gt(18)//筛选集合中年龄大于18的所有数据对象
}).get()//获取筛选到的所有数据(默认100条)

逻辑查询

代码语言:javascript复制
const _ = db.command
db.collection('test').where({//对数据集test进行where条件筛选
  _.or([
    {age: _.gt(18)},
    {gender: _.eq('男')}
  ])//筛选集合中年龄大于18的或者性别为男的所有数据对象
}).get()//获取筛选到的所有数据(默认100条)

分页查询

代码语言:javascript复制
db.collection('test').where({//对数据集test进行where条件筛选
  age: _.gt(18)//筛选集合中年龄大于18的所有数据对象
}).limit(10).skip(20).get()//获取筛选到第20条数据开始拉取10条。

排序查询

代码语言:javascript复制
db.collection('test').where({//对数据集test进行where条件筛选
  age: _.gt(18)//筛选集合中年龄大于18的所有数据对象
}).orderBy('age','asc').orderBy('gender','desc').get()//获取筛选到的所有数据(默认100条)
//先对年龄进行正序排序,再对性别倒叙排序。

查询指定列(不能true和false混用,否则会报错)

代码语言:javascript复制
db.collection('test').where({//对数据集test进行where条件筛选
  age: _.gt(18)//筛选集合中年龄大于18的所有数据对象
}).field({ age: true }).get()//获取筛选到的所有数据,只查询age列(默认100条)

.field({ age: false})//只屏蔽age列
.field({ age: true,gender:true})//只查询age和gender列
.field({ age: false,gender:false})//只屏蔽age和gender列

聚合查询

代码语言:javascript复制
  const $ = db.command.aggregate //获取聚合方法组对象
  db.collection('test').aggregate()//进行聚合查询
  .sort({//聚合阶段。根据指定的字段,对输入的文档进行排序
    score: 1,//从小到大
    age: -1//从大到小
  })
  .group({//分组设定
    _id: '$age',// 按 age 字段分组
    // 每组有一个 avgSales 字段,其值是组内所有记录的 sales 字段的平均值
    avgSales: $.avg('$sales'),//对sales字段进行求平均值操作,返回为avgSales
    sumPeople: $.sum(1),//统计总数量
    first:$.first('$score')//第一个分数,从小到大所以是最低分
    last:$.last('$score')//最后一个分数,从小到大所以是最高分
  })
  .limit(20)//默认统计完后返回前20条数据
  .end()//结束聚合返回结果

联表查询

1、基本结构

代码语言:javascript复制
const $ = db.command.aggregate//获取聚合方法组对象

lookup({//单条件查询
  from: <要连接的集合名>,
  localField: <输入记录的要进行相等匹配的字段>,
  foreignField: <被连接集合的要进行相等匹配的字段>,
  as: <输出的数组字段名>
})
//这样,查询出来的被链接的对象就是一个数组

2、示例

代码语言:javascript复制
db.collection('test').lookup({//单条件查询
  from: 'test2',//连接test2表
  localField: 'a',//test1表的a字段
  foreignField: 'b',//连接test2表的b字段
  as: 'test2List'//关联到的test2表的集合
})
//查询结果的结构大概是这样
[
  {
    ...,//test表的数据
    test2List:[{},{}]//这里是关联到的2表的数据列表
  },
  {
    ...,//test表的数据
    test2List:[{},{}]//这里是关联到的2表的数据列表
  },
]

更多详情请查看官方文档

数据库事务说明

当出现事务繁忙的报错时,请检查是否再同一个事务内,是否有并发数据库操作。

总结

  1. 作为一个懂绝大多数sql语言的前端开发,我觉得其余的都很方便,就查询这块学习成本很高,并且也没有写sql方便,官方文档还不全。所以,对数据查询处理要求比较高的,不是很实用。要联合云控制台的mysql使用。
  2. 能在前端直接操作数据库真的是太幸福了,真的有很多很简单的场景每次都要和后台进行交接真的是太麻烦了,云数据库算是完美的解决了这个痛点啊!我还记得我以前写过一个公用查询接口,不就是想让后台少点接口嘛。
  3. 数据储存也好完美啊,数组、对象等各种数据都能直接往里面扔,取出来就可以直接用,真的各种数据转换的问题也解决了!
  4. 数据更新也很完美啊,sdk提供了好多的直接更新数据的运算方法,都不用取出数据计算好再更新,巨方便的。
  5. 还是查询,查询这一块真的是我看的时间最长的,最终我还是认为很复杂的那种几十行几百行的查询sql要转换成SDK的写法,我会哭的,对大数据这一块我觉得真的不合适丫。不知道这边用的算法是怎样的,联表查询什么的性能怎么样,后续再研究吧。

0 人点赞