如何返回组合了另一个Observable结果的Observable以完成Firestore关联查询
核心问题原因
你遇到的类型不匹配问题本质是switchMap内返回的是子集合的Observable<TestResult[]>,tap仅执行副作用不会改变流的发射值,所以最终流的输出类型还是结果数组而非Test对象,用map操作符合并原test对象和结果数组即可解决。
单个Test对象补全实现
直接在子集合查询的管道中加入map,将查询到的结果合并到原Test对象中返回即可,最终流类型天然为Observable<Test>:
const result = this.firestore .doc<Test>(`tests/${testId}`) .valueChanges({ idField: 'id' }) .pipe( switchMap((test) => this.firestore .collection<TestResult>(`tests/${test.id}/results`) .valueChanges({ idField: 'name' }) .pipe( // 解构创建新对象避免修改原对象的副作用,同时返回完整Test结构 map((results) => ({ ...test, results })) ) ) );
可复用逻辑封装
你可以把补全逻辑抽成自定义RxJS操作符,后续单个查询、全列表查询都可以直接复用:
// 通用操作符,入参传入firestore实例即可 function attachTestResults(firestore: Firestore) { return <T extends Test>(source: Observable<T>) => source.pipe( switchMap(test => firestore.collection<TestResult>(`tests/${test.id}/results`) .valueChanges({ idField: 'name' }) .pipe(map(results => ({ ...test, results } as T))) ) ) }
复用示例1:单个查询
const result = this.firestore .doc<Test>(`tests/${testId}`) .valueChanges({ idField: 'id' }) .pipe(attachTestResults(this.firestore));
复用示例2:全测试列表补全
const testList$ = this.firestore .collection<Test>('tests') .valueChanges({ idField: 'id' }) .pipe( switchMap(tests => // 批量处理所有Test文档的补全逻辑 forkJoin(tests.map(test => of(test).pipe(attachTestResults(this.firestore)))) ) );
内容的提问来源于stack exchange,提问作者J4N
相关产品推荐
相关产品推荐

