Firestore循环查询偶发无结果问题求助
问题:Firestore查询集合数据时结果不稳定,有时返回有时无返回
问题描述
从Firestore获取集合数据时,查询行为不稳定——同一个确认存在的文档(例如日期20-09-2022对应的集合),有时能正常返回结果,有时却无结果返回。
已尝试的解决方案
- 关闭Firestore持久化(persistence)
- 使用
.get(Source.SERVER)强制指定从服务器查询
代码示例
for (int i = 1; i <= 31; i++) { String date = String.format("%02d", i) + "-" + String.format("%02d", currentMonth) + "-" + 2022; int finalI = i; monthRef.document(date) .collection("AttendanceSections") .document(student.getCurrentSection()) .collection("AttendanceStudents") .whereEqualTo("StudentID", student.getStudentId()) .get(Source.SERVER) .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { if (task.getResult().size() > 0) { for (QueryDocumentSnapshot document : task.getResult()) { StudentAttendance studentAttendance = document.toObject(StudentAttendance.class); studentAttendance.setDate(date); attendanceList.add(studentAttendance); } } } else { Log.d(TAG, "onComplete: " + task.getException().getMessage()); } if (finalI == 31) { Log.d(TAG, "onComplete: " + attendanceList.size()); progressBar.setVisibility(View.INVISIBLE); if (attendanceList.size() > 0) { drawDecorators(); } } } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { } }); }
关键细节
- 日期生成逻辑:
String date = String.format("%02d", i) + "-" + String.format("%02d", currentMonth) + "-" + 2022; - 已知
20-09-2022对应的集合确实存在,但查询该日期时结果不稳定 - Firestore数据结构:
- 根级集合对应目标月份,下一级为日期格式的文档ID(如
20-09-2022) - 每个日期文档下包含
AttendanceSections子集合,子集合的文档ID为班级标识 - 每个班级文档下包含
AttendanceStudents子集合,其中的文档存储单个学生的出勤记录,包含StudentID字段
- 根级集合对应目标月份,下一级为日期格式的文档ID(如
解决方向
1. 修复异步任务并发问题
当前循环发起31个异步查询,任务完成顺序完全不确定。如果finalI == 31的任务先执行完毕,其他查询可能还未返回结果,导致attendanceList统计不完整,看起来像是某些日期无返回。
可以使用Task.whenAll()等待所有查询完成后再处理结果:
List<Task<QuerySnapshot>> tasks = new ArrayList<>(); for (int i = 1; i <= 31; i++) { String date = String.format("%02d", i) + "-" + String.format("%02d", currentMonth) + "-" + 2022; Task<QuerySnapshot> task = monthRef.document(date) .collection("AttendanceSections") .document(student.getCurrentSection()) .collection("AttendanceStudents") .whereEqualTo("StudentID", student.getStudentId()) .get(Source.SERVER) .addOnCompleteListener(task1 -> { if (task1.isSuccessful() && task1.getResult().size() > 0) { for (QueryDocumentSnapshot document : task1.getResult()) { StudentAttendance studentAttendance = document.toObject(StudentAttendance.class); studentAttendance.setDate(date); attendanceList.add(studentAttendance); } } else if (!task1.isSuccessful()) { Log.d(TAG, "查询日期" + date + "失败: " + task1.getException().getMessage()); } }); tasks.add(task); } // 等待所有查询完成后统一处理 Task.whenAll(tasks).addOnCompleteListener(allTasks -> { Log.d(TAG, "所有查询完成: " + attendanceList.size()); progressBar.setVisibility(View.INVISIBLE); if (attendanceList.size() > 0) { drawDecorators(); } });
2. 校验日期格式匹配
打印生成的date字符串,和Firestore控制台里的文档ID做精确对比,确认是否存在格式差异(比如分隔符、大小写、空格等)。
3. 彻底清理缓存并检查权限
- 初始化Firestore时彻底禁用缓存:
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder() .setPersistenceEnabled(false) .build(); db.setFirestoreSettings(settings);
- 检查Firestore安全规则,确保当前用户拥有目标文档的读取权限。
4. 排查网络请求失败情况
在onFailure回调中添加日志,查看是否有请求因网络波动失败:
.addOnFailureListener(e -> { Log.e(TAG, "查询日期" + date + "失败: " + e.getMessage()); });
内容的提问来源于stack exchange,提问作者Muhammad Hanzilah
相关产品推荐
相关产品推荐

