Firestore如何实现Map键已存在时阻止更新避免预约重复预订
解决方案
核心实现思路
Firestore安全规则天然支持原子性的写入前置校验,完全可以解决并发预约的竞态问题,只需要校验:所有待新增的预约时段键,在当前员工文档的已预约Map中不存在即可。
具体安全规则代码
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 匹配员工可用性文档 match /employeeAvailability/{employeeId} { allow update: if isValidAppointmentUpdate() } } // 校验预约更新合法性的工具函数 function isValidAppointmentUpdate() { // 取出更新前后的完整预约Map let oldAppointments = resource.data.appointments; let newAppointments = request.resource.data.appointments; // 校验1:只能新增预约,不能修改/删除已存在的预约记录 let oldKeys = oldAppointments.keys(); let newKeys = newAppointments.keys(); let oldKeysAllRetained = oldKeys.all(key in newKeys && newAppointments[key] == oldAppointments[key]); // 校验2:所有新增的预约时段之前都不存在 let addedKeys = newKeys.filter(key, !(key in oldKeys)); // 若业务要求一次只能预约一个时段,可额外加校验:addedKeys.size() == 1 let noDuplicateAppointments = addedKeys.all(key, !(key in oldAppointments)); return oldKeysAllRetained && noDuplicateAppointments; } }
效果说明
- 当用户尝试预约已存在的时段时,更新请求会直接被安全规则拦截,返回
permission-denied错误,你可以在客户端捕获该错误,转换为“该预约时段已被预订”的用户提示。 - 规则校验是原子执行的,即使多个用户同时提交同一时段的预约请求,只有第一个写入的请求会通过,后续请求都会被拒绝,完全避免并发重复预约的问题。
可选优化
如果需要同时支持取消预约的场景,可以在规则里额外加权限判断,比如只有管理员或者预约人本人可以删除对应的预约键,避免普通用户随意删除他人预约记录。
内容的提问来源于stack exchange,提问作者Devon Allary
相关产品推荐
相关产品推荐

