You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
  • 客户端查询时直接读取用户文档的两个字段即可,不需要再查子集合

该方案唯一的成本是云函数的执行消耗,相比读配额的成本可以忽略不计,且统计结果查询响应速度最快,适合用户量较大的生产场景。

方案选型建议

  • 如果产品处于早期、用户量不大、查询频率低:优先选方案1,改造成本最低
  • 如果用户量过万、个人主页访问频率高:优先选方案2,长期成本更低、体验更好

内容的提问来源于stack exchange,提问作者Alejandra Hernandez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 14:06:05