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
}
}
}
因为事务期间的写操作会让对象加上事务锁,使两个并发的事务中的一个写入失败,直至事务提交。保证了写入用户表的记录用户位数唯一。