合并两个Firebase Firestore的Future<QuerySnapshot>失败,求解决方案
问题原因
你代码里的query1.docs是不可修改的List,调用addAll不会改变原有的文档列表,所以返回的还是仅包含query1结果的QuerySnapshot。
解决方案
方案一:使用Firestore原生OR查询(推荐)
Firestore支持复合OR查询,直接把两个玩家名称的条件合并成一个查询,减少网络请求次数,且结果自动排序:
Future<QuerySnapshot> mergeQueries() async { return FirebaseFirestore.instance .collection('practice') .orderBy('timeStamp', descending: true) .where('teamId', isEqualTo: widget.teamId) .where('checkSinglesDoubles', isEqualTo: dropDownType) .where(Filter.or( Filter('player1name', isEqualTo: playerNameFilter), Filter('player2name', isEqualTo: playerNameFilter), )) .get(); }
注意:首次运行会触发Firestore的索引创建提示,按照控制台指引创建复合索引即可。
方案二:手动合并查询结果(兼容旧版本或特殊场景)
如果必须保留两次查询,需要手动合并文档列表,再构造新的QuerySnapshot返回:
Future<QuerySnapshot> mergeQueries() async { final query1 = await FirebaseFirestore.instance .collection('practice') .orderBy('timeStamp', descending: true) .where('teamId', isEqualTo: widget.teamId) .where('checkSinglesDoubles', isEqualTo: dropDownType) .where('player1name', isEqualTo: playerNameFilter) .get(); final query2 = await FirebaseFirestore.instance .collection('practice') .orderBy('timeStamp', descending: true) .where('teamId', isEqualTo: widget.teamId) .where('checkSinglesDoubles', isEqualTo: dropDownType) .where('player2name', isEqualTo: playerNameFilter) .get(); // 合并文档并去重(避免同一文档被两个查询同时命中) final mergedDocs = {...query1.docs, ...query2.docs}.toList(); // 重新按timeStamp降序排序 mergedDocs.sort((a, b) => (b['timeStamp'] as Timestamp).compareTo(a['timeStamp'] as Timestamp)); // 构造新的QuerySnapshot返回 return QuerySnapshot( query: query1.query, docs: mergedDocs, metadata: query1.metadata, ); }
如果业务允许,更建议直接返回Future<List<DocumentSnapshot>>,省去构造QuerySnapshot的麻烦:
Future<List<DocumentSnapshot>> mergeQueries() async { final query1 = await FirebaseFirestore.instance .collection('practice') .orderBy('timeStamp', descending: true) .where('teamId', isEqualTo: widget.teamId) .where('checkSinglesDoubles', isEqualTo: dropDownType) .where('player1name', isEqualTo: playerNameFilter) .get(); final query2 = await FirebaseFirestore.instance .collection('practice') .orderBy('timeStamp', descending: true) .where('teamId', isEqualTo: widget.teamId) .where('checkSinglesDoubles', isEqualTo: dropDownType) .where('player2name', isEqualTo: playerNameFilter) .get(); final mergedDocs = {...query1.docs, ...query2.docs}.toList(); mergedDocs.sort((a, b) => (b['timeStamp'] as Timestamp).compareTo(a['timeStamp'] as Timestamp)); return mergedDocs; }
内容的提问来源于stack exchange,提问作者Joao Paulo Carvalho
相关产品推荐
相关产品推荐

