Notes
微信小程序
云开发实战

数据库基础

数据库是干什么的

数据库顾名思义,就是数据,即存放数据的仓库。这里面的数据指数字、文本、图片、视频等它们被放在一起,需要使用的时候可以拿出来。在现实生活中,有很多数据库的例子:

身份证数据库

我们每个人都有一张身份证,身份证上的信息如姓名、生日、性别、籍贯等都是数据库(表)里面存储的内容。在国家机关中,有一个将所有人的信息集中放在一起的仓库,它存储了十四亿条数据,每条数据又包含着姓名、生日、性别、籍贯等数据内容。当你在办理某些业务时,输入身份证号,即可看到你的其他信息,这就是一个常用的数据库查询的例子。此时,每个 身份证号 是唯一存在的,就是整个数据库的索引。

QQ 数据库

我们常常使用 QQ ,这是一个即时通信工具,实际上,在腾讯公司的技术部门,就有一个大型的数据库,这个数据库包含很多用户的信息,每个用户的信息就是数据库的一条数据,这个数据中有 QQ号、昵称、生日、个性签名等内容。此时,每个 QQ号 是唯一存在的,就是整个数据库的索引。

数据库的结构

传统的数据库的结构如下:

  • 数据库(database)
  • 数据表(table)
  • 数据行(row)
  • 字段(field),相当于 Excel 中的列,每个字段都有自己的数据类型。

在上面身份证例子中,整个户籍管理仓库就是一个数据库,这个数据库里面,可能有多张数据表,比如学籍表、身份证表、驾驶执照表等。以身份证表为例,这个表中存放着14亿条数据行,每个数据行标识着一个人。每一行都有一个唯一标识的字段,与其他字段区分开,这个字段就是身份证号,还有其他字段,比如姓名、民族、性别字段等。每个字段有不同的数据类型,身份证号数据类型为长数字,姓名的数据类型为字符串,出生日期的数据类型为日期

Excel 类比数据库

1

邮箱小程序设计

页面设计

这个小程序设计的主题是送信收信,所以仅安排了三个简单的界面,即

  • 注册界面
    1
  • 写信界面
    2
  • 收信界面
    3

数据库设计

在这个简单的小程序中,我们需要存储用户信息信件信息。因此我们的数据库中需要两个数据表用户信息数据表中需要存储用户的头像、昵称、ID,信件信息需要存储信件的收件人、内容和发件人ID。两个数据库可以通过**昵称(收件人姓名)**联系起来。

2

编程实现

页面实现

TabBar

    "tabBar": {
        "list": [{
            "pagePath": "pages/index/index",
            "text": "注册"
        }, {
            "pagePath": "pages/dend/index",
            "text": "发信"
        }, {
            "pagePath": "pages/receive/index",
            "text": "收信"
        }]
    },

注册页面

包含登录按钮,姓名输入框以及注册按钮。

<!--index.wxml-->
<view class="container">
  <!-- 头像 -->
  <view ><image class="avatar" src="{{avatar}}"></image></view>
  <button bindtap="Login">点击使用微信登录</button>
  <input bindinput="bindKeyInput" type="text" class="inputBox" placeholder="填写你的姓名"/>
  <button style="margin-top: 20rpx;" bindtap="Yes">注册</button>
</view>

写信页面

<!--pages/dend/index.wxml-->
<view class="container">
  <strong>发信</strong>
  <input bindinput="inputRecer" type="text" class="inputBox" placeholder="填写收件人"/>
  <input bindinput="inputContent" type="text" class="inputBox" placeholder="填写内容"/>
  <button bindtap="Sendit">发送</button>
</view>

收信页面

这里需要使用列表渲染。

<view class="container">
  <strong>收件箱</strong>
  <!-- 列表渲染 -->
  <view class="Mailcard" wx:for='{{MailList}}' wx:key='index'>
   <view style="display:block">内容:{{item.content}} </view>
      <view style="display:block">收件人:{{item.rece}}</view>
 </view>
</view>

数据库创建

创建集合

打开云开发控制台,在数据库中创建两个集合。分别取名TestBaseMails,分别存储用户信息和信件信息。

1

:::caution 图中其他数据库集合和本例子无关,请不用理会。 :::

设置读写权限

在集合页面,设置数据权限所有用户可读,仅创建者可读写

2

如此,数据库创建就完成了。

注册功能

需求分析

在页面注册时,我们需要要求用户填写自己的姓名,再通过微信登录获取用户的openid作为唯一的标识。然后将拿到的信息与已存在的数据库比对,如果这个用户注册过,就提示注册过了,如果没有,就向数据库TestBase添加一条新的用户数据。

用户登录

使用微信提供的 API 获取用户登录,并得到其头像。

  Login(e) {
    // 微信登录
    var that = this
      //调用登录接口
      wx.login({
        success: function () {
          wx.getUserInfo({
            success: function (res) {
            }
          })
        }
      })
      wx.getUserProfile({
        desc:'获取用户信息',
        success: (res) => {
          // 获取userInfo的状态数据
          console.log(res)
          this.setData({
            // 获取头像
            avatar: res.userInfo.avatarUrl,
            isLogin:1
          })
        },
      })
  },

获取openid

由于微信直接提供的 openid 是秘密的,因此我们必须要解密之后才能使用 openid ,这里就要借助云函数进行实现了。

在 cloudfuctions 文件夹创建云函数 getOpenId ,图中其他的函数不需要理会,与本例子无关。
1

getOpenId 的 index 文件中创建 openid 解析函数,如下:

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({ // 初始化云开发环境
  env: cloud.DYNAMIC_CURRENT_ENV // 当前环境的常量
})
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  // 返回当前用户的身份信息,用于数据库记录和查询
  return {
    event,
    openid: wxContext.OPENID,
    fromopenid: wxContext.FROM_OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}

云函数调用

回到页面的 index.js 文件,在文件中调用这个云函数。

async getOpenId() {
    const {
      result: {
        // 创建调用结果
        openid,
        fromopenid
      }
    } = await (await this.cloud()).callFunction({
        // 声明要调用的云函数
      name: 'getOpenId'
    }).catch(e => {
      let flag = e.toString()
      flag = flag.indexOf('FunctionName') == -1 ? flag : '请在cloudfunctions文件夹中getOpenId上右键,创建部署云端安装依赖,然后再次体验'
      wx.hideLoading()
      wx.showModal({
        content: flag, //  "网络服务异常,请确认网络重新尝试!"
        showCancel: false
      })
      throw new Error(flag)
    })
    // 返回解密结果
    if (openid !== "") return openid
    return fromopenid
  },

然后我们尝试登录,查看是否正常获取了 openid :

1

如图,已经获取到了数据容器中。

填写姓名

使用 input 以及其自带的响应事件,创建输入框。

<input bindinput="bindKeyInput" type="text" class="inputBox" placeholder="填写你的姓名"/>
data: {
    //...
    // 输入内容
    inputValue: "占位姓名",
    //...
  },
bindKeyInput: function (e) {
    this.setData({
        inputValue: e.detail.value
    })
},

写入数据库

在上面的步骤中,我们已经得到了用户的 openid 以及用户填写的姓名,现在,我们要把注册信息写到数据库中。

首先,为注册按钮绑定事件。

先调用获取 openid 函数,得到 openid (上面只创建了功能,并没有调用) 。

    this.getOpenId().then(async openid => {
      console.log("OpenID: " + openid)
      this.setData({
        UserID: openid
      })
    })

接着,初始化云环境:

    const db = wx.cloud.database({
      // 在下面填写你的云开发 ID
      env: ''
    })

然后在数据表中判断这个 ID 是否已经注册过,这就需要用到 db.where.get API。让我们看一下官方是如何解释这个方法的:

Collection.where(condition: Object): Collection

指定查询条件,返回带新查询条件的新的集合引用

参数
condition: Object
查询条件

返回值
Collection

在这里,我们使用 where 去查询这个 openid 是否已经存在。

db.collection('TestBase').where({
      // 筛选条件
      _openid: this.data.UserID
    }).get().then(ress => {
        // 如果存在 如何处理
    })

可以通过 data.length 来判断数据行是否为空,如果已经存在,那么我们就应该要提示用户已注册

      if (ress.data.length != 0) {
        wx.showModal({
          title: '抱歉',
          content: '用户已存在',
        })
      }

如果不为空,我们就要使用 db.collection('').add 方法添加数据:

       db.collection('TestBase').add({
          // data 字段表示需新增的 JSON 数据,在这里向数据库写入数据
          data: {
            // 让 id 标识为用户唯一的 openid
            _id: this.data.UserID,
            // 头像
            Avatar:this.data.avatar,
            // 姓名
            Name:this.data.inputValue
          },
          success: function (res) {
            // res 是一个对象,其中有 _id 字段标记刚创建的记录的 id
            console.log(res)
            wx.showModal({
              title: '成功',
              content: '上传成功',
            })
          }
        })

我们执行一下,观察数据库中是否已经添加了新的数据:

1

显然,这里已经增加了一条新的用户数据。

数据库调用步骤

经过上面的例子,我们可以总结出数据库调用的步骤:

一、初始化云环境

cloud.init({ // 初始化云开发环境
  env: cloud.DYNAMIC_CURRENT_ENV // 当前环境的常量
})

二、声明数据库

    const db = wx.cloud.database({
      // 在下面填写你的云开发 ID
      env: ''
    })

三、调用API进行处理

比如上面的查询和新增,实际上,数据库有增删改查等能力,这在微信小程序文档中有详细的说明,也可以参考这篇文章 (opens in a new tab)

写信功能

需求分析

在写信功能中,我们需要指定收件人,以及写入信的内容,这里定义了两个输入框,用于获取这两个内容。获取得到这些信息之后,我们首先要到用户数据表中判断这个收件人是否为我们的用户,如果不是,那么就提示,如果是,就把这封信写入到信件数据表中。

文本框信息获取

  data: {
    Content:'',
    Rece:'',
    RecrID:''
  },
  inputContent: function (e) {
    this.setData({
      Content: e.detail.value
    })
  },
  inputRecer: function (e) {
    this.setData({
      Rece: e.detail.value
    })
  },

判断是否填写了内容

发送按钮点击事件中进行判断。

   if(this.data.Content===''|this.data.Rece===''){
      wx.showModal({
        title: '注意',
        content: '请先输入完整内容',
      })
    }

判断是否存在这个收信人

同样是调用 where 方法来判断数据表中是否有这个收件人数据:

db.collection('TestBase').where({
      // 筛选条件
      Name:this.data.Rece
    }).get().then(ress => {
 
    })

这里这个函数返回了一个数据 ress ,这个数据中包含了数据库中这个 Name 用户对应的所有数据,我们可以使用 ress.data[0] 得到它。我们通过 console.log 方法打印出 ress 的内容。现在我们看看控制台输出的 ress 究竟是什么:

1

显然,它返回了一个 Array 数组,这个数组只有一个元素,即 data[0] ,这个元素中返回了四个参数,我们需要的是这个 _openid 参数,它表示了收件人的唯一标识。因此可以通过ress.data[0] 得到它,并把它放到临时的容器中。

db.collection('TestBase').where({
      // 筛选条件
      Name:this.data.Rece
    }).get().then(ress => {
      // 判断返回的data长度是否为0,如果为0的话就证明数据库中没有存在该数据,然后进行添加操作
      // 得到了对应姓名的 openid
      // highlight-start
      console.log(ress);
      this.setData({
        RecrID:ress.data[0]._openid
      })
      // highlight-end
      if (ress.data.length === 0) {
        wx.showModal({
          title: '抱歉',
          content: '用户不存在',
        })
        return;
      }
      else{
        // 用户存在,添加信件数据,另一个数据库
      }
    })

写入信件数据

与写入用户数据十分类似,不再赘述:

// 用户存在,添加信件数据,另一个数据库
db.collection('Mails').add({
    // data 字段表示需新增的 JSON 数据,在这里向数据库写入数据
    data: {
    // 收件人姓名
    rece: this.data.Rece,
    // 收件人id
    receID:this.data.RecrID,
    // 新建内容
    content:this.data.Content
    },
    success: function (res) {
    // res 是一个对象,其中有 _id 字段标记刚创建的记录的 id
    console.log(res)
    wx.showModal({
        title: '成功',
        content: '上传成功',
    })
    }
})

收信

需求分析

收信时,我们需要拿着自己的姓名去信件数据库逐一匹配,如果是发给自己的信,就拿出来,其他的不管。然后通过微信能力列表渲染到界面。

数据库比对

同样是使用 where 方法进行比对,将通过比对 openid 就可以得到只属于自己的内容:

onShow: function () {
    var that=this;
    const db = wx.cloud.database({
      // 填写你的云开发 ID
      env: 'nannan-1g1q4u2i02398ecf'
    })
    // 在数据库里面添加新表 TestBase
    db.collection('Mails').where({
      // 筛选条件,这样查询之后只会获取发给自己的信息,空着就行,不用填参数
      _openid:''
    }).get().then(ress => {
      console.log(ress)
      that.setData({
        MailList:ress.data
      })
    })
  },

为什么在 onShow 函数中进行?因为我们希望,每次打开这个页面就去更新我们获得的数据信息。进行这个步骤之后,数据容器 MailList 就得到了全部属于我的信件。

列表渲染

我们看看 MailList 中有什么:

1

这与云开发数据库中的信息能够对上:

2

除了一条为张三的数据外,所有 aaa 的数据都获取下来了。

然后列表渲染:

  <view class="Mailcard" wx:for='{{MailList}}' wx:key='index'>
   <view style="display:block">内容:{{item.content}} </view>
      <view style="display:block">收件人:{{item.rece}}</view>
 </view>

实现结果:
2