1、新建用户集合user,存储用户信息,里面包括了当前用户是第几位,发现小程序云数据库并没有类似mysql一样的自动增长字段(表示用户位数),需要自己实现。
2、为了实现自动增长,需要新建一个集合counters
手动插入一条记录,用于保存当前总共有几位用户,注意sequence_value字段的类型是数字
{
"_id":"productid",
"sequence_value": 0
}
当有用户访问时,将counters集合下唯一记录的sequence_value字段加1,并作为当前用户位数添加到用户表。
exports.main = async (event, context) => { const aaaRes = await db.collection('counters').doc('productid').get() await db.collection('counters').doc('productid').update({ // data 传入需要局部更新的数据 data: { sequence_value: db.command.inc(1) } }) let place = ++aaaRes.data.sequence_value //place代表第XX位用户 await db.collection('user').add({ // data 字段表示需新增的 JSON 数据 data: { _openid: cloud.getWXContext().OPENID, place, name: event.name, mobile: event.mobile, _createTime: Date.now(), } }) }
自动增长字段就完成了,这时还需要考虑的就是不同的用户同时访问云函数时的冲突情况。
3、冲突指两个用户同时访问云函数时,获得的sequence_value值是一样的,添加到用户表的用户位数也相同,不够准确。这时,可以使用小程序的事务解决冲突。
const db = cloud.database() const _ = db.command // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() try { const result = await db.runTransaction(async transaction => { const aaaRes = await transaction.collection('counters').doc('productid').get() if (aaaRes.data) { await transaction.collection('counters').doc('productid').update({ data: { sequence_value: _.inc(1) } }) let place = ++aaaRes.data.sequence_value //place代表全国第XX位用户 await transaction.collection('user').add({ // data 字段表示需新增的 JSON 数据 data: { _openid: wxContext.OPENID, place, name: event.name, mobile: event.mobile, } }) console.log(`transaction succeeded`) // 会作为 runTransaction resolve 的结果返回 return { place, } } else { // 会作为 runTransaction reject 的结果出去 await transaction.rollback(-100) } }) return { success: true, place: result.place, } } catch (e) { console.error(`transaction error`, e) return { success: false, error: e } } }
因为事务期间的写操作会让对象加上事务锁,使两个并发的事务中的一个写入失败,直至事务提交。保证了写入用户表的记录用户位数唯一。