You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Firebase双查询实现获取userOne/userTwo均不含当前用户的数据

问题原因

你当前的实现存在逻辑交集问题:

  • streamOne返回所有jobState=1且userOne≠当前用户的文档,会包含「userTwo是当前用户」的文档
  • streamTwo返回所有jobState=1且userTwo≠当前用户的文档,会包含「userOne是当前用户」的文档
    两个流合并后,只要满足任意一个条件的文档都会被输出,自然会返回当前用户存在于userOne或userTwo字段的结果。
修复方案

分两步调整即可达到需求:

  1. 合并两个流的查询结果后先做文档去重,避免同一份文档被两个流重复返回
  2. 对合并后的结果做二次过滤,仅保留同时满足userOne≠当前用户且userTwo≠当前用户的文档

完整实现代码如下:

// 提前获取当前用户uid,避免重复调用可能出现的空安全问题
final currentUid = FirebaseAuth.instance.currentUser?.uid;
if (currentUid == null) {
  // 可自行处理用户未登录场景,比如返回空流
  return const Stream.empty();
}

var streamOne = FirebaseFirestore.instance
  .collection('jobs')
  .where('jobState', isEqualTo: 1)
  .where('userOne', isNotEqualTo: currentUid)
  .snapshots();
var streamTwo = FirebaseFirestore.instance
  .collection('jobs')
  .where('jobState', isEqualTo: 1)
  .where('userTwo', isNotEqualTo: currentUid)
  .snapshots();

// 用RxDart合并流并过滤数据
final filteredJobsStream = CombineLatestStream.combine2(
  streamOne,
  streamTwo,
  (QuerySnapshot snap1, QuerySnapshot snap2) {
    // 用文档ID做去重
    final docMap = <String, QueryDocumentSnapshot>{};
    for (var doc in snap1.docs) docMap[doc.id] = doc;
    for (var doc in snap2.docs) docMap[doc.id] = doc;
    
    // 二次过滤符合要求的文档
    return docMap.values.where((doc) {
      final jobData = doc.data() as Map<String, dynamic>;
      return jobData['userOne'] != currentUid && jobData['userTwo'] != currentUid;
    }).toList();
  }
);
可选优化方案

如果你的jobs数据量较大,不想在客户端做二次过滤,可以在写入jobs文档时新增一个relatedUsers数组字段,把userOne和userTwo的uid都存入该数组,之后直接用单个查询就能拿到结果,不需要合并流:

final filteredJobsStream = FirebaseFirestore.instance
  .collection('jobs')
  .where('jobState', isEqualTo: 1)
  .where('relatedUsers', whereNotIn: [currentUid])
  .snapshots();

内容的提问来源于stack exchange,提问作者beax07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 07:15:04