云开发数据库查询不到刚插入的数据?
我在小程序里用云开发往集合里插入了一条记录,但紧接着去查却查不到,这是为啥?明明返回的_res.success是true啊。
我试过加延时再查,还是不行。是不是权限问题?但读写权限都设成“仅创建者可读写”了,而且是在同一个用户下操作的。
wx.cloud.database().collection('logs').add({
data: { msg: 'test', time: Date.now() },
success: res => {
console.log('插入成功', res)
// 紧接着查询
wx.cloud.database().collection('logs').where({ msg: 'test' }).get({
success: qRes => console.log('查询结果', qRes.data) // 这里经常是空数组
})
}
})
先说原理。云开发的数据库底层是分布式架构,数据写入后,主节点虽然立刻返回成功,但从节点的同步、索引的更新都需要一点点时间。你那个
success: true只代表写入请求被主节点接收了,不代表立刻就能被查到。这玩意儿跟咱们本地 MySQL 不一样,不能指望写完立刻读。你代码里用
where({ msg: 'test' })去查,走的是索引查询,索引更新有延迟,所以经常查不到。解决办法有三个思路,按推荐程度排序:
第一个办法,也是最推荐的,直接用插入返回的
_id来查。插入成功后,返回值里会有这条记录的_id,用这个_id做doc()查询,走主键索引,这个是强一致的,肯定能查到。第二个办法,如果你非要用条件查询,那就别在回调里立刻查。云开发的数据同步一般在几百毫秒到一两秒之间,你可以用
setTimeout延迟一下,虽然这个办法有点笨,但确实能解决问题。第三个办法,重新审视一下你的业务逻辑。很多时候我们插入完立刻查,是因为想拿到插入后的完整数据。但其实
add返回的_id已经够用了,你完全可以把插入的数据自己在前端拼一下,没必要非去数据库再查一遍。我之前就这么干过,后来想通了,纯属多此一举。再说一下你提到的权限问题。权限设置成「仅创建者可读写」是没问题的,同一个用户插入后立刻查,权限上不会有阻碍。真正的问题就是分布式数据库的最终一致性,这个在云开发的官方文档里其实有提过,叫「读写一致性」相关的内容。
总结一下,用
doc(_id)查就完事了,别折腾条件查询。如果业务上确实需要条件查询,那就接受这个延迟,或者换一种设计思路。对了,你那个
Date.now()存进去是个时间戳数字,后续查询的时候记得用数字去匹配,别用字符串,这个坑我也踩过。