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

使用Firestore的getDocuments查询获取数据时返回空数组的问题排查求助

排查Firestore getDocuments返回空数组的问题

我来帮你捋捋Firestore查询返回空数组的几个常见坑,结合你的代码场景逐一分析:

  • 目标文档/子集合不存在
    你的查询路径是users/{username}/notifications,首先要确认几个点:

    • UserDefaults里存储的username和Firestore中users集合下的文档ID是否完全一致(Firestore对大小写、特殊字符敏感,比如"John"和"john"是两个不同的文档);
    • 该用户文档下是否真的存在名为notifications的子集合,有没有拼写错误(比如少写字母、大小写错误)。
  • Firestore安全规则限制
    如果你的Firestore安全规则没有正确配置,可能会导致查询被拦截,返回空结果(甚至不报错)。比如规则没有验证用户身份,或者路径匹配逻辑错误。可以先临时将规则改为开放测试(仅限开发环境):

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /{document=**} {
          allow read, write: if true;
        }
      }
    }
    

    如果测试后能拿到数据,说明问题出在安全规则上,再针对性调整规则(比如只允许用户读取自己的通知)。

  • IGNotification初始化失败(compactMap过滤掉所有元素)
    你用了compactMap来转换文档数据,要是IGNotification(with: $0.data())这个初始化方法对某些文档返回了nil,compactMap会把这些无效元素全部过滤,最终得到空数组。
    建议先单独打印每个文档的原始数据,看看是否存在字段缺失、类型不匹配的情况(比如Firestore里存的是数字,你代码里用字符串接收)。

  • 异步逻辑或UserDefaults时机问题
    虽然你的代码里用guard判断了username是否存在,但要确保调用getNotifications的时候,UserDefaults里的username已经被正确设置。比如有没有可能在用户登录流程还没完成时就调用了这个函数?

调试建议

修改你的查询代码,增加更多调试日志,帮你定位问题:

public func getNotifications( completion: @escaping ([IGNotification]) -> Void ) {
    guard let username = UserDefaults.standard.string(forKey: "username") else {
        print("UserDefaults中没有找到username")
        completion([])
        return
    }
    print("当前查询的username:\(username)")
    let ref = firestoreDatabase.collection("users").document(username).collection("notifications")
    ref.getDocuments { snapshot, error in
        // 先检查错误
        if let error = error {
            print("Firestore查询错误:\(error.localizedDescription)")
            completion([])
            return
        }
        // 检查是否拿到文档
        guard let documents = snapshot?.documents else {
            print("未获取到任何文档")
            completion([])
            return
        }
        print("成功获取到\(documents.count)个通知文档")
        // 打印第一个文档的原始数据
        if let firstDoc = documents.first {
            print("第一个文档数据:\(firstDoc.data())")
        }
        // 分步处理映射
        let notifications = documents.compactMap { doc in
            let notification = IGNotification(with: doc.data())
            if notification == nil {
                print("映射失败的文档数据:\(doc.data())")
            }
            return notification
        }
        print("映射后得到\(notifications.count)个有效通知")
        completion(notifications)
    }
}

通过这些日志,你能清楚看到是哪一步出了问题——是没拿到文档,还是映射失败,或者是username本身就不对。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 16:38:14