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

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字段

解决方向

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:40:23