Swift中如何实现Firestore文档计数不额外消耗读配额?
Firestore 关注/粉丝数统计优化方案
你当前的实现逻辑确实会产生极高的读配额消耗:每查询一次两个统计值,消耗的读次数等于用户关注数+粉丝数的总和,用户量级上来后成本会非常高。以下是两种可落地的优化方案:
方案1:使用官方聚合计数查询 count()
Firestore 原生提供了专门的集合计数聚合查询,不会拉取全量文档内容,收费规则为每扫描1000条文档仅收取1次读配额,相比原方案成本可以降低几百到上千倍,且只需要修改客户端代码,不需要额外开发后端逻辑。
修改后的代码如下:
func fetchUserStats() { guard let uid = user.id else {return} let followingGroup = DispatchGroup() let followersGroup = DispatchGroup() var followingCount = 0 var followersCount = 0 followingGroup.enter() COLLECTION_FOLLOWING.document(uid).collection("user-following").count.getAggregation { snapshot, _ in followingCount = Int(snapshot?.count ?? 0) followingGroup.leave() } followersGroup.enter() COLLECTION_FOLLOWERS.document(uid).collection("user-followers").count.getAggregation { snapshot, _ in followersCount = Int(snapshot?.count ?? 0) followersGroup.leave() } // 等待两个计数请求完成后赋值 DispatchQueue.global().async { followingGroup.wait() followersGroup.wait() DispatchQueue.main.async { self.user.stats = UserStats(following: followingCount, followers: followersCount) } } }
注:这里用DispatchGroup优化了原有的嵌套回调逻辑,两个请求可以并行执行,提升查询速度
方案2:预存统计字段(生产环境最优方案)
如果个人主页的访问频率很高,或者统计量级超十万级,更推荐用预存统计的方案,查询时只需要消耗1次读就能拿到两个统计值,成本和性能都是最优的。
实现逻辑如下:
- 在用户文档中新增
followingCount、followersCount两个数值字段,初始值为0 - 编写Firebase云函数触发器,监听关注关系集合的新增、删除事件:
- 当用户A关注用户B时,触发
onCreate触发器,用事务将A的followingCount+1,B的followersCount+1 - 当用户A取关用户B时,触发
onDelete触发器,用事务将A的followingCount-1,B的followersCount-1
- 当用户A关注用户B时,触发
- 客户端查询时直接读取用户文档的两个字段即可,不需要再查子集合
该方案唯一的成本是云函数的执行消耗,相比读配额的成本可以忽略不计,且统计结果查询响应速度最快,适合用户量较大的生产场景。
方案选型建议
- 如果产品处于早期、用户量不大、查询频率低:优先选方案1,改造成本最低
- 如果用户量过万、个人主页访问频率高:优先选方案2,长期成本更低、体验更好
内容的提问来源于stack exchange,提问作者Alejandra Hernandez
相关产品推荐
相关产品推荐

