AngularFire2动态查询Firestore集合仅返回单条结果求助
解决AngularFire2查询多个UID仅返回单个结果的问题
看起来你是想一次性查询匹配多个UID的user_previews文档,但当前的代码逻辑是逐个传入ID并发起单独查询,再加上switchMap的特性导致了只返回单个结果的问题,我来帮你梳理下:
问题根源
你的代码里用ids$.next()逐个传入UID,而switchMap的核心特性是:当新的事件(新UID)到来时,会立即取消前一个Observable的订阅。如果你的forEach是同步执行的,两个next几乎同时触发,第一个查询可能还没来得及返回完整结果就被取消了;就算第一个查询刚好返回了结果,第二个查询的订阅会替换掉第一个,最终你可能只会看到其中一个结果(你说的“最早的用户”大概率是第一个查询先返回的结果)。
更重要的是:你其实不需要逐个查询单个UID,Firestore支持用in操作符一次性查询多个匹配的文档,这才是更高效、符合你需求的做法。
解决方案1:一次性查询多个UID(推荐)
直接收集所有需要查询的UID,用where('id', 'in', [...ids])发起单次查询:
// 先从friendRequests中提取所有需要查询的UID const targetUserIds = this.friendRequests.map(request => request.id_sent); // 发起批量查询 const queriedUsers$ = this.afs.collection('user_previews', ref => ref.where('id', 'in', targetUserIds) ).valueChanges(); // 订阅结果 queriedUsers$.subscribe(users => { console.log(users); // 现在会返回所有匹配的用户文档数组 });
注意:Firestore的in操作符最多支持同时查询10个值,如果你的UID数量超过10,需要把数组拆分成多个chunk,然后合并查询结果,我会在下面的方案里说明。
解决方案2:动态添加UID时的处理(如果需要实时更新)
如果你的UID是陆续获取的(不是一次性得到所有),可以把Subject改成接收UID数组,再处理批量查询:
import { forkJoin, of } from 'rxjs'; import { map, switchMap, take } from 'rxjs/operators'; // 定义接收UID数组的Subject const userIds$ = new Subject<string[]>(); // 处理批量查询,自动拆分超过10个UID的情况 const queriedUsers$ = userIds$.pipe( switchMap(ids => { if (ids.length === 0) return of([]); // 拆分数组为最多10个元素的chunk const idChunks = []; for (let i = 0; i < ids.length; i += 10) { idChunks.push(ids.slice(i, i + 10)); } // 并行查询所有chunk,然后合并结果 return forkJoin( idChunks.map(chunk => this.afs.collection('user_previews', ref => ref.where('id', 'in', chunk) ).valueChanges().pipe(take(1)) // take(1)只取一次结果,不需要实时监听的话可以加 ) ).pipe( map(results => results.flat()) // 把多个chunk的结果数组合并成一个 ); }) ); // 订阅结果 queriedUsers$.subscribe(users => { console.log(users); }); // 传入所有UID(后续也可以随时传入新的UID数组) userIds$.next(this.friendRequests.map(r => r.id_sent));
为什么原来的代码只返回一个结果?
再回头看你的原代码:
- 每次
ids$.next()都会触发switchMap创建一个新的查询Observable,同时取消上一个查询的订阅 - 如果两个
next触发间隔极短,第一个查询可能被直接取消,只有第二个查询的结果会返回;如果第一个查询刚好在第二个next之前完成,你会看到第一个结果,而第二个查询的订阅会替换掉第一个,后续如果第二个查询返回结果会覆盖之前的日志(或者你没注意到) - 而且这种逐个查询的方式效率很低,远不如批量查询
内容的提问来源于stack exchange,提问作者cerealex
相关产品推荐
相关产品推荐

