Firestore中实现用户聊天禁言功能的最优实现方案咨询
你当前的实现方案不合理,存在较多隐患,不建议线上使用。
现有方案的问题
- 把状态标识和时间戳拼接为字符串存储,每次校验用户发言权限时都需要额外做字符串拆分解析,不仅客户端实现繁琐,在Firestore安全规则中实现字符串解析逻辑极易出问题,甚至可能出现权限校验漏洞。
- 字符串类型的字段无法利用Firestore的索引能力,你无法高效查询所有处于禁言状态的用户、指定时间段内即将解封的用户,全表扫描的成本和性能都极差。
- 数据结构不透明,后续维护成本高,其他开发者接手时需要额外理解字段的拼接规则,很容易写出不兼容的代码。
更优的实现方案
拆分出两个独立字段,使用对应的数据类型存储信息,数据结构如下:
Users | --- lvBnCNGuTahS9xjT51oB | --- isPermanentlyBanned (Boolean) // 永久禁言标识,默认值为false --- banExpireTimestamp (Number) // 临时禁言解封时间戳,未被临时禁言时值为null
权限校验逻辑
无论在客户端代码还是Firestore安全规则中,校验逻辑都非常简洁:
- 若
isPermanentlyBanned为true,直接禁止用户发言 - 若
isPermanentlyBanned为false,再判断banExpireTimestamp:- 若
banExpireTimestamp为null,允许发言 - 若当前时间小于
banExpireTimestamp,禁止发言 - 若当前时间大于等于
banExpireTimestamp,允许发言
- 若
方案优势
- 逻辑清晰无歧义,不需要额外做字段解析,不会出现解析类的bug
- 支持灵活配置:可单独设置永久禁言、单独设置临时禁言,两种配置互不冲突
- 支持高效查询:可直接通过
banExpireTimestamp筛选指定时间段内解封的用户,Firestore可走索引查询,性能高成本低 - 扩展性强:后续需要新增禁言原因、操作人等字段时,直接在用户文档下新增对应字段即可,不需要改动现有逻辑
如果你希望减少字段数量,也可以仅保留banExpireTimestamp一个字段:约定值为-1时代表永久禁言,值为null时代表正常,值大于当前时间时代表临时禁言即可,不过更推荐使用两个字段的方案,可读性更高。
内容的提问来源于stack exchange,提问作者Taha Sami
相关产品推荐
相关产品推荐

