Firebase使用where not-in查询时如何动态更新排除数组的值?
实现方案
核心思路
你原来的写法存在的问题是:Firestore的查询条件在调用collection方法时就会固定读取当前arrayId的值,后续修改arrayId不会自动更新查询条件,因此需要用响应式的方式管理排除ID列表:
- 用RxJS的
BehaviorSubject存储需要排除的contactProId列表,每次列表更新时自动生成新的查询流 - 每次拿到查询结果后,自动将结果中的
contactProId加入排除列表,实现后续查询自动过滤已拉取过的ID
完整代码实现
import { BehaviorSubject, switchMap, tap, Observable } from 'rxjs'; // 替换原来的arrayId定义 private excludedProIds: Set<string> = new Set(); private excludedIds$ = new BehaviorSubject<string[]>([]); findAllContacts(): Observable<Message[]> { return this.excludedIds$.pipe( // 每次排除ID列表更新时,切换到新的Firestore查询流 switchMap(excludedIds => { return this.db.collection('messages', ref => { return ref .where("clientId", "==", this.clientId) // not-in不支持空数组,空数组时传入无意义值避免报错 .where("contactProId", "not-in", excludedIds.length ? excludedIds : ['_placeholder_']) // 修正你原代码的笔误:参数是idField不是isField }).valueChanges({ idField: 'id' }) as Observable<Message[]>; }), // 拿到查询结果后更新排除ID列表 tap((messages: Message[]) => { messages.forEach(msg => { this.excludedProIds.add(msg.contactProId); }); // 推送新的排除列表,触发查询条件更新 this.excludedIds$.next(Array.from(this.excludedProIds)); }) ); }
注意事项
- Firestore官方对
not-in操作符有10个值的上限限制,如果你的排除ID数量超过10个,该查询会直接报错,这种场景建议改为前端过滤返回结果,或者调整业务逻辑改用分页查询等其他方案 - 如果你不需要实时监听数据变化,仅做单次拉取,可以将
valueChanges替换为get()方法再转为Observable,减少不必要的长连接开销 - 用
Set存储排除ID是为了自动去重,避免重复添加相同ID到查询条件中
内容的提问来源于stack exchange,提问作者Franck Gomez
相关产品推荐
相关产品推荐

