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

Firebase查询指定条件捐赠请求数据失败:求解决方案

解决Firestore查询无结果的问题

核心问题分析

  1. 查询条件完全写反:你需要查询userEmail不等于当前用户邮箱的请求,但代码中错误使用了.where("userEmail", isEqualTo: userEmailID),这只会返回当前用户自己的请求,和需求完全相悖。
  2. 仅获取单个文档:当前代码只取查询结果的第一个文档,会丢失其他符合条件的请求数据。
  3. 缺少复合索引:Firestore同时使用多个where条件和orderBy时,必须创建对应的复合索引,否则查询会失败或无结果。

修正后的完整代码

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final controller = Get.put(UserController());
  bool donationRequestsLoading = true;
  // 改为List存储所有符合条件的请求
  List<Map<String, dynamic>> donationRequests = [];

  Future<void> fetchDonationRequests() async {
    try {
      final userEmailID = controller.user.value.email;
      final userBlood = controller.user.value.bloodGroup;
      print('blood group: $userBlood');

      // 空值校验,避免邮箱/血型为空导致查询异常
      if (userEmailID == null || userBlood == null) {
        print("用户邮箱或血型为空,无法执行查询");
        return;
      }

      QuerySnapshot querySnapshot = await FirebaseFirestore.instance
          .collection("Requests")
          .where("status", isEqualTo: "Pending")
          .where("bloodGroup", isEqualTo: userBlood)
          // 修正为"不等于当前用户邮箱"的条件
          .where("userEmail", isNotEqualTo: userEmailID)
          .orderBy(FieldPath.documentId, descending: true)
          .get();

      // 处理所有符合条件的文档
      if (querySnapshot.docs.isNotEmpty) {
        donationRequests = querySnapshot.docs.map((doc) {
          final data = doc.data() as Map<String, dynamic>;
          // 额外存储文档ID,方便后续操作(如更新状态)
          data['docId'] = doc.id;
          return data;
        }).toList();
      } else {
        donationRequests = [];
      }
    } catch (e) {
      print("获取捐赠请求失败: $e");
      // 针对性提示常见错误
      if (e.toString().contains("requires an index")) {
        print("请根据控制台提示的链接创建复合索引");
      } else if (e.toString().contains("Missing or insufficient permissions")) {
        print("请检查Firestore安全规则是否允许读取Requests集合");
      }
    } finally {
      setState(() {
        donationRequestsLoading = false;
      });
    }
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      fetchDonationRequests();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: [
            const EPrimaryHeaderContainer(
              child: Column(
                children: [
                  EHomeAppBar(),
                  SizedBox(height: ESizes.spaceBtwInputFields),
                  BloodGroupandNextDonation(),
                  SizedBox(height: ESizes.spaceBtwSections),
                ],
              ),
            ),
            const RequestToBloodBank(),
            const SizedBox(height: 28),

            // 功能按钮区域
            const Padding(
              padding: EdgeInsets.symmetric(horizontal: ESizes.defaultSpace),
              child: Column(
                children: [
                  Row(
                    children: [
                      PostBloodRequest(),
                      SizedBox(width: 12),
                      BloodBanks(),
                      SizedBox(width: 12),
                      DonateBlood(),
                    ],
                  ),
                  SizedBox(height: ESizes.spaceBtwInputFields),
                ],
              ),
            ),

            // 捐赠请求列表区域
            ESectionHeading(
              title: 'Donation Requests',
              showActionButton: true,
              onPressed: () {
                Get.to(() => const DonationRequestsList());
              },
            ),
            const SizedBox(height: 1),

            donationRequestsLoading
                ? const Padding(
                    padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
                    child: EShimmerEffect(
                      width: double.infinity,
                      height: 110,
                      radius: 16,
                    ),
                  )
                : donationRequests.isEmpty
                    ? const Center(
                        child: Text(
                          "无捐赠请求",
                          style: TextStyle(fontSize: 16, color: Colors.grey),
                        ),
                      )
                    // 改为横向列表展示多个请求
                    : SizedBox(
                        height: 110,
                        child: ListView.builder(
                          scrollDirection: Axis.horizontal,
                          padding: const EdgeInsets.symmetric(horizontal: 20),
                          itemCount: donationRequests.length,
                          itemBuilder: (context, index) {
                            return DonationRequests(donationMap: donationRequests[index]);
                          },
                        ),
                      ),
            const SizedBox(height: 10),
          ],
        ),
      ),
    );
  }
}

额外注意事项

  1. 复合索引创建:运行代码后如果控制台提示需要创建索引,复制提示中的链接到浏览器,按照引导完成索引创建即可。
  2. 安全规则配置:确保Firestore安全规则允许读取Requests集合,示例规则如下(可根据实际需求调整):
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /Requests/{request} {
      allow read: if request.auth != null; // 仅允许登录用户读取
      allow write: if request.auth != null;
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:54:52