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
相关产品推荐
相关产品推荐

