Angular Firestore 如何将文档中嵌套的引用数组转换为对应实体数组
实现方案
你需要借助RxJS的异步流处理能力,批量拉取引用对应的B集合数据,再回填到每个A对象中,具体实现如下:
前提假设
你已经实现了根据B文档引用获取B实体的服务方法,示例签名如下:
// b.service.ts getBByRef(bRef: DocumentReference): Observable<B> { // 内部实现为根据ref查询单条B文档,返回格式化后的B实体 return this.afs.doc<B>(bRef).get().pipe( map(snap => ({id: snap.id, ...snap.data()} as B)) ) }
同时你的A类型定义中已添加存储B实体数组的字段,例如:
interface A { id: string; // 其他原有字段 bRefs: DocumentReference[]; // 替换为你实际的B引用数组字段名 bs: B[]; // 新增存储完整B实体的字段 }
核心实现代码
修改后的getAs方法如下:
import { switchMap, forkJoin, map, of } from 'rxjs'; getAs() { this.aService.getAs().pipe( // 第一步:格式化原始A数组 map(rawData => rawData.map(e => ({ id: e.payload.doc.id, ...(e.payload.doc.data() as {}) } as A))), // 第二步:对每个A实例拉取关联的所有B数据 switchMap(aList => forkJoin( aList.map(a => { // 无关联B引用时直接返回原对象 if (!a.bRefs?.length) { return of({...a, bs: []}); } // 批量拉取当前A关联的所有B return forkJoin( a.bRefs.map(bRef => this.bService.getBByRef(bRef)) ).pipe( // 回填B数组到A对象 map(bList => ({...a, bs: bList})) ); }) )) ).subscribe((processedAList) => { // 此处获取到的就是已填充完B数组的完整A集合 this.aArray = processedAList; }); }
优化方案(减少请求次数)
如果关联的B引用存在大量重复,你可以先把所有A的B引用收集去重,一次性拉取所有B数据,再按引用映射回对应的A对象,能大幅减少数据库请求次数,适合数据量较大的场景。
注:Firebase的
DocumentReference实例可直接用===判断是否指向同一文档。
内容的提问来源于stack exchange,提问作者Schmetti
相关产品推荐
相关产品推荐

