Flutter下Firestore子集合数据快速获取优化方案咨询
优化Firestore子集合数据获取方案
你的代码慢的核心原因是串行发起每个日期文档的Reimbursement查询,当月如果有30天,就等于30次网络请求的耗时累加,自然会拖到8-10秒。以下两种优化方案可以解决这个问题:
方案1:并行执行所有日期查询(无需修改数据结构)
用Future.wait替代串行的await,让所有日期的Reimbursement查询同时发起,总耗时等于最慢的单个请求时间,而非所有请求时间之和。
修改后的代码:
getAllReimbursement(month, year) async { allReimbursement.clear(); List<ReimbursementModel> reimbursementList = []; // 获取当月所有日期文档 final monthRef = await FirebaseFirestore.instance .collection("Company") .doc(ConstantValue.companyId) .collection("Year") .doc(year) .collection(month) .get(); final dateDocs = monthRef.docs; // 生成所有日期的Reimbursement查询Future列表 final queryFutures = dateDocs.map((dateDoc) { return dateDoc.reference .collection("Reimbursement") .where("sendTo", isEqualTo: ConstantValue.userEmail) .get(); }).toList(); // 并行等待所有查询完成 final queryResults = await Future.wait(queryFutures); // 合并所有查询结果 for (final result in queryResults) { reimbursementList.addAll( result.docs.map((doc) => ReimbursementModel.fromJson(doc.data())).toList(), ); } allReimbursement = reimbursementList; return reimbursementList; }
这个方案能把耗时从8-10秒压缩到1-2秒左右,见效最快,不需要调整现有数据结构。
方案2:扁平化数据结构(极致性能优化)
Firestore的深层子集合查询天生需要遍历父文档,最优解是把报销数据扁平化存储,避免嵌套层级。可以单独创建一个Reimbursements集合,每个文档包含查询所需的所有维度字段:
新数据结构
Reimbursements(集合) -> reimbursement_id(文档) - companyId: "xxx" // 公司ID - year: "2024" // 年份 - month: "05" // 月份 - date: "15" // 日期 - sendTo: "user@example.com" // 收件人邮箱 - ...其他报销相关字段
优化后的查询代码
getAllReimbursement(month, year) async { allReimbursement.clear(); // 一次查询直接获取所有符合条件的报销数据 final querySnapshot = await FirebaseFirestore.instance .collection("Reimbursements") .where("companyId", isEqualTo: ConstantValue.companyId) .where("year", isEqualTo: year) .where("month", isEqualTo: month) .where("sendTo", isEqualTo: ConstantValue.userEmail) .get(); final reimbursementList = querySnapshot.docs .map((doc) => ReimbursementModel.fromJson(doc.data())) .toList(); allReimbursement = reimbursementList; return reimbursementList; }
额外优化
给companyId、year、month、sendTo创建复合索引(Firestore会在你第一次执行这个查询时提示你创建索引的链接,直接点击生成即可),能让查询速度再提升一个档次,总耗时通常在几百毫秒以内,完全满足页面加载前获取数据的需求。
内容的提问来源于stack exchange,提问作者sadil manjiyani
相关产品推荐
相关产品推荐

