如何在Swift中统计Firestore中动态新增的设备文档数量?
在Swift中统计Firebase Devices集合的文档数量
我需要统计Firebase里devices集合下动态新增的文档(比如device0、device1这类命名的文档)总数,尝试了两种方法但都没达到预期效果:
方法一:逐个检查文档是否存在
原本计划按顺序遍历device0、device1...直到找不到文档,以此统计总数,但未成功。尝试的代码如下:
func checkDevice3Exists() { let db = Firestore.firestore() let clientDocRef = db.collection("devices").document("device3") clientDocRef.getDocument { (document, error) in if let document = document, document.exists { let dataDescription = document.data().map(String.init(describing:)) ?? "nil" print("Document data: \(dataDescription)") if dataDescription.contains("\"device3\"") { print ("field exists") } else { print("field doesnt exist") } } else { print("Document does not exist") } } }
问题分析:这种方式依赖文档命名严格连续,一旦中间有文档缺失(比如device1被删除但device2存在),就会提前终止统计,结果不准确;而且多次发起Firestore请求,效率低、成本高。
方法二:获取集合所有文档计数
尝试通过获取整个集合的文档快照来统计数量,代码如下:
func countDevices(completion: @escaping (Int) -> Void) { let db = Firestore.firestore() db.collection("devices").getDocuments { (querySnapshot, error) in if let error = error { print("Error getting documents: \(error)") completion(0) } else { let deviceCount = querySnapshot?.documents.count ?? 0 completion(deviceCount) } } } // 调用代码 countDevices { deviceCount in print("Total: \(deviceCount)") }
问题分析:如果集合文档数超过1000条,getDocuments默认只会返回前1000条,导致计数错误;另外如果用户没有集合的读取权限,也会返回0或报错。
推荐解决方案:使用Firestore聚合查询(Count)
Firestore提供了专门的聚合查询API,只返回计数结果,无需传输所有文档数据,效率更高且无1000条限制,代码示例:
func countDevices(completion: @escaping (Result<Int, Error>) -> Void) { let db = Firestore.firestore() // 发起聚合计数查询 db.collection("devices").count.get { result in switch result { case .success(let snapshot): completion(.success(Int(snapshot.count))) case .failure(let error): completion(.failure(error)) } } } // 调用方式 countDevices { result in switch result { case .success(let count): print("设备总数:\(count)") case .failure(let error): print("统计失败:\(error.localizedDescription)") } }
注意事项:
- 确保当前用户拥有
devices集合的读取权限(在Firebase控制台的规则中配置) - 聚合查询会消耗少量Firestore读取配额,但比获取所有文档的消耗低很多
内容的提问来源于stack exchange,提问作者Yusuf Furkan Ayyıldız
相关产品推荐
相关产品推荐

