云函数查询_从0到1造个小程序 实战篇6:后端数据库设计&云函数编写

点击上方“水之Coding工房”并关注,更多好玩的等着你~ 大家好,我是本公众号唯一御用小编, 水水是也!

今天给大家带来的是学习专题——从0到1造个小程序 的实战篇6后端数据库设计&云函数编写

前面的实战篇,我们已经一步步走下来,将咱们的小程序时间管理小助手包含的4个页面:首页事项详情页事项计时页记录总结页,完成了他们的页面设计逻辑设计

「P.S.想要进行回顾的话,可以点击上方的专辑进行哦!」

但是我们知道,仅仅只是把页面跳转逻辑写出来的话肯定是不够的。而且对于数据的存储和持久化的话,必然是需要用到云端的数据库进行存储,并辅之以操作数据库的方法(增加、删除、修改、查询),才能将一个功能完整、使用体验良好的小程序展现出来。

那么本次实战篇,将会对小程序的后端数据库设计,以及云函数的实战编写进行不同程度的讲解,可能多多少少有些部分会没有涉及到甚至错漏,如果有的话也请麻烦提出啦!那么本篇,我们继续冲冲冲~

本文主要分为3个部分,主要分为云开发环境初始化数据库设计云函数实战编写

对于云开发的基础知识如果已经有所遗忘了的话,可以点击【从0到1造个小程序 · 基础篇4:云开发基础知识】进行回顾!

那么接下来,我们就一点点地开始吧~

0feddeb7fcfa8bed88d44b48c3fea498.png

1.  云开发环境初始化

针对小程序项目中与云开发平台绑定的初始化的话,首先是要在根目录中的app.js中的onLaunch()生命周期函数中初始化云卡发,部分具体代码如下:

import { CLOUD_ENV_ID } from './config'

App({
onLaunch() {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
wx.cloud.init({
traceUser: true,
env: CLOUD_ENV_ID
})
}
})

从import可以看到,我们在./config.js内部引入了CLOUD_ENV_ID变量,这个就是我们的云开发id,至于怎么获得自己的这个id的话,详见【从0到1造个小程序 · 基础篇4:云开发基础知识】。

所以,我们在小程序根目录下新建config.js,写入自己的云开发ID:

//config.js
export const CLOUD_ENV_ID = 'XXXXXXX' // 云开发环境ID

那么,云开发平台环境与咱们的小程序项目的绑定初始化工作就完成了。

2. 数据库设计

什么是数据库呢?

数据库是一个"记录保存系统",是"人们为解决特定的任务,以一定的组织方式存储在一起的相关的数据的集合",是"一个数据仓库"。严格地说,数据库是"按照数据结构来组织、存储和管理数据的仓库"。在经济管理的日常工作中,常常需要把某些相关的数据放进这样"仓库",并根据管理的需要进行相应的处理。

例如,企业或事业单位的人事部门常常要把本单位职工的基本情况(职工号、姓名、年龄、性别、籍贯、工资、简历等)存放在表中,这张表就可以看成是一个数据库中的其中一个表。有了这个"数据仓库",我们就可以根据需要随时查询某职工的基本情况,也可以查询工资在某个范围内的职工人数等等。

这些工作如果都能在计算机上自动进行,那我们的人事管理就可以达到极高的水平。此外,在财务管理、仓库管理、生产管理中也需要建立众多的这种"数据库",使其可以利用计算机实现财务、仓库、生产的自动化管理。

那么,针对小程序云开发的数据库的话,又是怎么样的呢?我们来看看官方文档的叙述:

dac662ac68a56d1136de7397b4eb865f.png
官方文档写的

JSON数据库,那么JSON是什么呢?

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。

简单而言,JSON有两种表示结构,对象和数组。对象结构以”{”大括号开始,以”}”大括号结束。中间部分由0或多个以”,”分隔的”key(关键字)/value(值)”对构成,关键字和值之间以”:”分隔,语法结构如代码。其中关键字是字符串,而值可以是字符串,数值,true,false,null,对象或数组。

{
key1:value1,
key2:value2,
...
}

数组结构以”[”开始,”]”结束。中间由0或多个以”,”分隔的值列表组成,语法结构如代码。

[
{
key1:value1,
key2:value2
},
{
key3:value3,
key4:value4
}
]

其实,对于JSON的话,在我们页面配置(组件引用)、小程序配置文件的话我们都是有用到了的,还不熟悉的话可以去回顾一下。那么,知道了数据库的一个存储数据的格式以后的话,我们需要思考的就是,我们要存哪些数据,以及怎么设计这两个关键问题了。

(1)存哪些数据

对于这个问题,我们回顾思考一下咱们的小程序的一个业务流程:

  1. 首先,用户需要登录才能够使用我们的小程序。那么,存储用户信息就是必要的,而识别唯一用户的话可以通过「openId」进行,所以我们可以直接存储每一个授权登录小程序的用户。

  2. 其次,对于登陆以后,小程序的使用核心是“对时间管理事项进行管理”,那么就肯定涉及到的是「时间管理事项」的内容属性的存储。进一步思考,时间管理事项包含哪些属性呢?

    回顾之前创建小程序时需要填写的内容:「事项标题」「所需用时」。同时,因为要事项对应出来是哪一个用户的,所以还需要加一个「userId」绑定;因为是时间管理,还有考虑到后面事项进行记录的用时,以及首页的列表展示需要,所以我们还需要加上「已用时」「事项最后更新时间」「事项创建时间」

  3. 针对事项详情以及记录总结页的话,我们知道,对于每一个时间管理事项,都会有对应该事项的一个记录列表。所以也应该创建一个对应每一个事项的记录列表,对应实现方式通过绑定一个事项ideventId。对于记录列表使用一个records数组,里面存储每一次记录的:「开始时间」「结束时间」「总结内容」「持续时间」

(2)怎么设计

针对以上的三个部分,对应的就是3张表啦!以下是设计/创建数据库表集合的一个流程:

  1. 所以我们打开我们各自的云开发界面:
cfb17938b965f07e400867c2a69b20ad.png
点击云开发
  1. 点击数据库栏目:
52415a59159344255ff1e24949b17b02.png
云开发界面
  1. 在云开发数据库中创建 userseventsevent-records 三个集合。
46d1ce57a642f03f547aea94f13c2a71.png
创建完成展示

其中user代表用户集合;events代表事项详细信息集合;event-records代表各事项记录总结集合。

  1. event-records 中添加 eventId 为唯一索引,在 users 中添加 _openid 为唯一索引。
cbea64241e0ee0d4bd7e59e1ce437052.png
event-records中添加eventId为唯一索引
c29c03064e897ba120cc42971d3bca35.png
users中添加openId为唯一索引

以上,就是关于数据库的设计了,其中关于对数据库存储哪些哪些数据这一块需要加深记忆,因为在后面的云函数编写中需要着重使用。

3. 云函数实战编写

从之前的页面逻辑设计中,相信大家都有看到像下面的这一类函数:

  static editEventTitle(eventId, eventTitle, eventTime) {
return wx.cloud.callFunction({
name: 'editEventTitle',
data: {
eventId,
eventTitle,
eventTime
}
})
}
static getEventData(eventId) {
return wx.cloud.callFunction({
name: 'getEventData',
data: { eventId }
})
}

static removeEvent(eventId) {
return wx.cloud.callFunction({
name: 'removeEvent',
data: { eventId }
})
}

可以看到其中他们的共同点都有wx.cloud.callFunction,然后内部再指定namedata,给予页面JS调用以后,就能调取数据了。那长这个样子的这类函数,到底是什么来的呢?

585edde3f4337ab345b9ba7b92f6edfb.png

其实,看看cloud.callFunction,就可以隐约猜到,这个就是微信所提供的调用云函数的API(应用程序接口,可以理解为提供能够使用的方法)。

那么,既然我们之前声明了这么多的云函数名称,那么现在小程序后端的开发,就要将这些方法给一一实现了。所以,我们先来看看,我们之前声明了多少个云函数方法呢?水水已经整理好了,见下:

login   //注册openid
removeEvent //删除单个事项
addEventRecord //添加事项记录
addUser //创建用户
createEvent //创建事项
editEventTitle //修改事项标题与用时
getEventData //获取单个事项信息
getEventList //获取全部事项

对于我们这个小程序项目中所涉及到的云函数的话,都属于操作数据库的方法,而且对于编写云函数的话也是有一套模板可供修改定制的,所以别看云函数这么多,其实写起来也并不难。

同时,对于该部分的学习资料的话可以看往期推文【从0到1造个小程序 · 基础篇4:云开发基础知识】中的数据库部分进行回顾,看了之后再进行云函数的实战,一定会有一种畅快之感哦!

那么我们该如何去编写云函数呢?首先,右键小程序环境,选择【新建node.js云函数】,按照上面所声明方法名进行命名,即可完成云函数的新建。

c1b43cc19b8b9aa39613104418cd9488.png
右键示例图

然后可以看到,新建云函数以后出现了3个文件,而我们需要进行编辑就是index.js:

12868c8cb9f5162d397c3bf0fae0de83.png
指引示例

那么,我们先写一个login云函数方法作为栗子吧:

对于login方法的话,其实就是将用户的openId获取并保存到user表中,这个操作听起来就不难,我们直接看看代码的,其中有必要的注释加以说明:

//cloudfunctions\login\index.js
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXX' //你的云开发id
})
//获取数据库实例
const db = cloud.database()

exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
//获取openid
const openId = wxContext.OPENID
//操作数据库的users集合根据openid获取数据
const result = await db
.collection('users')
.where({
_openid: openId
})
.get()

const idData = result.data[0]
//如有则返回id,否则userid返回空
return {
userId: idData && idData._id && idData._openid ? idData._id : null,
openId
}
}

编辑完成并保存后,还需要部署云函数,才能够真正将云函数应用到我们的小程序项目中的,具体方法的话,只需要右键对应云函数文件夹,选择【上传并部署:云端安装依赖(不上传node_modules)】,即可完成云函数的部署,然后小程序就能够调用我们的云函数了。没错,就是这么简单!

db8423004844a6bd1f08a4a8c49e1979.png

那么,login云函数编写完成。

像这样子的云函数还有7个!

不过没事,具体的云函数的用途和说明的话也已经在上面列举了,大家也可以先试一试如果自己写的话会怎么去写,还是不会需要加深记忆的话也可以再看看,多学学。以下的话,将展示剩余所有的云函数编写示例,其中也有必要的代码注释辅助理解。

那么,代码轰炸开始了!

//cloudfunctions\removeEvent\index.js
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXXX'
})
//新建数据库实例
const db = cloud.database()
const _ = db.command

exports.main = async (event, context) => {
const { eventId } = event
//如果没有该事项对应的id,则直接结束
if (!eventId) {
return
}

try {
await db
//根据eventId删除与该事项相关的记录条目
.collection('event-records')
.where({
eventId
})
.remove()

//根据eventId删除与该事项条目
await db
.collection('events')
.doc(eventId)
.remove()
} catch (e) {
console.log(e)
}
}

//cloudfunctions\addEventRecord\index.js
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXXXXXXXX'
})
const db = cloud.database()
const _ = db.command

exports.main = async (event, context) => {
//从参数中获取到事项id,开始时间,结束时间,总结内容,持续时间
const { eventId, beginDate, endDate, summary, time } = event
//若没有对应事项,则返回
if (!eventId) {
return
}

try {
//根据事项id及参数内容更新插入新纪录
await db
.collection('event-records')
.where({
eventId
})
.update({
data: {
records: _.push([
{
summary,
beginDate,
endDate,
time
}
])
}
})
//在事项events表中更新最后更新时间
await db
.collection('events')
.doc(eventId)
.update({
data: {
time: _.inc(parseInt(time)),
lastUpdate: endDate
}
})
} catch (e) {
console.log(e)
}
}
//cloudfunctions\addUser\index.js
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXXXX'
})
const db = cloud.database()

exports.main = async (event, context) => {

const wxContext = cloud.getWXContext()
//新增用户,在users表中用openid新插入到表中
try {
return await db.collection('users').add({
data: {
_openid: wxContext.OPENID
}
})
} catch (e) {
console.log(e)
}
}
//cloudfunctions\createEvent\index.js
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXXXX'
})
const db = cloud.database()
const _ = db.command

exports.main = async (event, context) => {
//从参数中获取到事项标题,用户id,事项预计用时
const { eventTitle, userId, eventTime } = event
//如果有参数为空则方法结束
if (!eventTitle || !userId || !eventTime) return

try {
//根据参数以及时间在events表中插入事项
const event = await db.collection('events').add({
data: {
userId,
title: eventTitle,
eventTime:eventTime,
createDate: new Date(),
lastUpdate: null,
time: 0
}
})
//事项记录表中也需要用eventsId初始化该事项的记录表
await db.collection('event-records').add({
data: {
eventId: event._id
}
})
} catch (e) {
console.log(e)
}
}
//cloudfunctions\editEventTitle\index.js
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXXXX'
})
const db = cloud.database()

exports.main = async (event, context) => {
//根据参数获取到id、事项标题、所需时间
const { eventId, eventTitle, eventTime } = event
//若其中有一项为空则返回
if (!eventId || !eventTitle || !eventTime) return

try {
//根据eventid更改对应事项的属性,并返回
const result = await db
.collection('events')
.doc(eventId)
.update({
data: {
title: eventTitle,
eventTime:eventTime
}
})
result.data = {
eventId,
eventTitle,
eventTime
}
return result
} catch (e) {
console.log(e)
return e
}
}
//cloudfunctions\getEventData\index.js
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXXX'
})
const db = cloud.database()
const _ = db.command

exports.main = async (event, context) => {
//从参数中获取到事项id
const { eventId } = event
//若为空则直接结束
if (!eventId) {
return
}

try {
//根据事项id获取对应事项数据
const eventInfo = await db
.collection('events')
.doc(eventId)
.get()
//根据事项id获取该事项的所有记录
const eventRecords = await db
.collection('event-records')
.where({
eventId
})
.get()
//根据上面的两个查询拼接返回
return { eventInfo, eventRecords }
} catch (e) {
console.log(e)
}
}
//cloudfunctions\getEventList
const cloud = require('wx-server-sdk')

cloud.init({
env: 'XXXXXX'
})
const db = cloud.database()
const _ = db.command

exports.main = async (event, context) => {
//根据参数获取用户id
const { userId } = event

if (!userId) {
return
}

try {
//根据用户id从事项表中获取所有事项
return await db
.collection('events')
.where({
userId
})
.get()
} catch (e) {
console.log(e)
}
}

所有云函数编写完成后,再分别进行部署,云函数就能够被自由调用了!


以上,就是本次后端设计的主要内容。至此,小程序的基本功能已经全部完成。

■ Over ■

          历史推荐          

 从0到1造个小程序 · 实战篇4:页面设计之计时页 从0到1造个小程序 · 实战篇5:页面设计之记录总结页 从0到1造个小程序 · 实战篇3:页面设计之事项详情页 从0到1造个小程序 · 实战篇2:页面组件化设计&首页逻辑设计 ★

b5bf88d164ee4d0a2ef56703921064c1.png

我是水水

我们下期再见

本公众号不具备留言功能

有什么问题的话欢迎在后台输入框中回复哦~da00d81c6e8b054db7a61acb2b1d7d09.png

0470fd83746e794187ffeffbf40315fc.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值