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

Flutter中无法从Cloud Firestore引用字段获取数据

解决Firestore中通过引用字段获取关联文档的问题

你遇到的_JsonDocumentReference是Firestore内部对文档引用的序列化实现,它和DocumentReference完全兼容,无需额外转换就能直接调用查询方法。下面提供几种可行的实现方案:

方法一:直接通过引用获取作者文档

遍历有声书文档时,直接利用idAutor引用字段查询对应的作者文档,整合有声书与作者信息:

Future<List<Audiolibro>> getAudiolibros() async {
  List<Audiolibro> listaAudiolibros = [];
  CollectionReference audiolibros = bbdd.collection("audiolibros");
  QuerySnapshot<Object?> response = await audiolibros.get();

  // 用for循环替代forEach,避免异步操作无法等待的问题
  for (var element in response.docs) {
    final datos = element.data() as Map<String, dynamic>;
    // 直接将_JsonDocumentReference转为DocumentReference使用
    DocumentReference<Map<String, dynamic>> autorRef = datos['idAutor'] as DocumentReference<Map<String, dynamic>>;
    
    // 获取作者文档快照
    DocumentSnapshot<Map<String, dynamic>> autorSnapshot = await autorRef.get();
    if (autorSnapshot.exists) {
      Map<String, dynamic> autorData = autorSnapshot.data()!;
      
      // 创建Audiolibro对象,根据你的类结构填充字段
      Audiolibro audiolibro = Audiolibro(
        id: element.id,
        titulo: datos['titulo'],
        // 关联作者信息
        autor: Autor(
          id: autorSnapshot.id,
          nombre: autorData['nombre'],
          // 其他作者字段按需添加
        )
      );
      listaAudiolibros.add(audiolibro);
    }
  }

  return listaAudiolibros;
}

方法二:先提取作者ID再单独查询

如果需要先获取作者文档ID再发起查询,可通过引用的id属性提取ID,再从Autores集合查询:

Future<List<Audiolibro>> getAudiolibros() async {
  List<Audiolibro> listaAudiolibros = [];
  CollectionReference audiolibros = bbdd.collection("audiolibros");
  QuerySnapshot<Object?> response = await audiolibros.get();

  for (var element in response.docs) {
    final datos = element.data() as Map<String, dynamic>;
    DocumentReference<Map<String, dynamic>> autorRef = datos['idAutor'] as DocumentReference<Map<String, dynamic>>;
    // 提取作者文档ID
    String autorId = autorRef.id;
    
    // 通过ID查询作者文档
    DocumentSnapshot<Map<String, dynamic>> autorSnapshot = await bbdd.collection("autores").doc(autorId).get();
    if (autorSnapshot.exists) {
      Map<String, dynamic> autorData = autorSnapshot.data()!;
      // 创建并添加Audiolibro对象
      Audiolibro audiolibro = Audiolibro(
        id: element.id,
        titulo: datos['titulo'],
        autor: Autor(
          id: autorId,
          nombre: autorData['nombre'],
        )
      );
      listaAudiolibros.add(audiolibro);
    }
  }

  return listaAudiolibros;
}

性能优化方案(批量查询)

如果有声书数量较多,多次单独查询会影响性能,可使用Future.wait批量获取所有作者文档,减少网络请求次数:

Future<List<Audiolibro>> getAudiolibros() async {
  List<Audiolibro> listaAudiolibros = [];
  CollectionReference audiolibros = bbdd.collection("audiolibros");
  QuerySnapshot<Object?> response = await audiolibros.get();

  // 收集所有有声书数据及对应的作者引用
  List<Map<String, dynamic>> audiolibroWithAutorRef = [];
  for (var element in response.docs) {
    final datos = element.data() as Map<String, dynamic>;
    DocumentReference<Map<String, dynamic>> autorRef = datos['idAutor'] as DocumentReference<Map<String, dynamic>>;
    audiolibroWithAutorRef.add({
      'audiolibroDatos': datos,
      'audiolibroId': element.id,
      'autorRef': autorRef,
    });
  }

  // 批量获取所有作者文档
  List<DocumentSnapshot<Map<String, dynamic>>> autorSnapshots = await Future.wait(
    audiolibroWithAutorRef.map((item) => item['autorRef'].get())
  );

  // 整合有声书与作者信息
  for (int i = 0; i < audiolibroWithAutorRef.length; i++) {
    var item = audiolibroWithAutorRef[i];
    var autorSnapshot = autorSnapshots[i];
    if (autorSnapshot.exists) {
      Map<String, dynamic> autorData = autorSnapshot.data()!;
      Audiolibro audiolibro = Audiolibro(
        id: item['audiolibroId'],
        titulo: item['audiolibroDatos']['titulo'],
        autor: Autor(
          id: autorSnapshot.id,
          nombre: autorData['nombre'],
        )
      );
      listaAudiolibros.add(audiolibro);
    }
  }

  return listaAudiolibros;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:13:31