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

Firestore嵌套集合数据获取异常:内存溢出/应用崩溃求助

Firestore嵌套集合数据获取问题排查与修复

问题描述

我有Firestore嵌套集合结构doctors→visits,想要获取该集合及子集合的全部数据并存入列表,用于ListView展示。

数据模型如下:

class allReport {
  late String? date;
  late String? doctorNote;
  String? doctoreName;
  late String? marketerNote;
  late String? id;

  allReport({
    required this.date,
    required this.doctorNote,
    required this.marketerNote,
    required this.id,
    required this.doctoreName
  });

  static allReport fromJson(
          Map<String, dynamic> json, String id, String doctoreName) =>
      allReport(
        id: id,
        doctoreName: doctoreName,
        doctorNote: json['doctorNote'],
        date: json['date'],
        marketerNote: json['marketerNote'],
      );
}

我尝试用以下代码获取数据,通过doc.reference.parent.parent获取visits文档的父级ID,进而获取父级数据:

List<allReport> _docReports = [];
List<allReport> _filtereddocReports = [];

Future<List<allReport>> getAlldocsData() async {
    var col = await _firestore.collectionGroup('visits');

    var snapshot_child = await col.get();
     snapshot_child.docs.map((doc) async {

      var ChildDocument = doc;

    var snapshot_parent =  await _firestore
          .collection('doctors')
          .doc(ChildDocument.reference.parent.parent?.id)
          .get();

      _docReports =  allReport.fromJson(
           ChildDocument.data() ,snapshot_parent.data()?['name'] ,doc.reference.parent.parent?.id ?? '') as List<allReport>;

    }).toList();

    
    print('**********************${_docReports.map((e) => e.doctoreName)}');
    
    setState(() {
      _filtereddocReports = _docReports;
    });
    return _filtereddocReports;
}

当前代码无法打印数据,还出现“内存溢出”错误,偶尔应用崩溃,需要排查问题。

问题原因分析

  • 异步处理失效:map内的async回调返回Future,但直接调用toList()不会等待所有异步任务完成,导致后续代码在数据未处理完时就执行,_docReports始终为空。
  • 类型转换错误:allReport.fromJson返回单个对象,却被强行转为List<allReport>,触发类型异常,进而引发内存溢出或崩溃。
  • 列表赋值逻辑错误:每次循环都用单个对象覆盖_docReports,而非添加元素,即使无类型错误,最终列表也只会保留最后一条数据。
  • 参数传递错误:fromJson的参数顺序与构造函数不匹配,把医生ID传给了id参数,不符合业务逻辑。

修正后的代码

List<allReport> _docReports = [];
List<allReport> _filtereddocReports = [];

Future<List<allReport>> getAlldocsData() async {
  // 清空列表,避免重复添加数据
  _docReports.clear();
  
  // 获取所有visits集合的文档
  final snapshotChild = await _firestore.collectionGroup('visits').get();
  
  // 等待所有异步请求完成
  await Future.wait(snapshotChild.docs.map((doc) async {
    // 获取父级doctor文档ID,为空则跳过
    final doctorId = doc.reference.parent.parent?.id;
    if (doctorId == null) return;
    
    // 获取父级doctor文档数据
    final snapshotParent = await _firestore.collection('doctors').doc(doctorId).get();
    final doctorName = snapshotParent.data()?['name'] ?? '';
    
    // 转换为allReport对象并添加到列表
    final report = allReport.fromJson(
      doc.data(),
      doc.id, // visits文档ID作为report的id
      doctorName // 医生名称作为doctoreName
    );
    _docReports.add(report);
  }));
  
  print('**********************${_docReports.map((e) => e.doctoreName)}');
  
  setState(() {
    _filtereddocReports = List.from(_docReports); // 创建副本避免引用问题
  });
  
  return _filtereddocReports;
}

额外优化建议

  • 冗余字段优化性能:如果visits数据量较大,逐个请求doctor文档会产生大量网络请求,建议在visits文档中冗余存储doctorName字段,直接从visits文档读取即可,无需额外请求父集合。
  • 实时数据监听:若需要实时更新数据,可使用collectionGroup('visits').snapshots()监听数据流,替代单次get()请求。
  • 代码规范修正:遵循Dart命名规范,将类名allReport改为大驼峰格式AllReport。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:43:20