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

如何在Flutter中实现Supabase关联表的复杂过滤查询?

在Flutter中用Supabase实现屏蔽规则下的日记查询

要实现「获取未被当前登录用户屏蔽的日记,且日记发布者未被当前用户屏蔽」的需求,核心是在Supabase查询中排除两类数据:当前用户主动屏蔽的日记、当前用户屏蔽的作者发布的日记。以下是两种可行的实现方式:

方式一:使用子查询过滤(简洁直观)

通过NOT IN结合子查询,直接排除被屏蔽的日记ID和作者ID:

// 获取当前登录用户ID(务必处理未登录情况)
final currentUserId = supabase.auth.currentUser?.id;
if (currentUserId == null) {
  // 未登录逻辑,比如返回空列表或提示用户登录
  return [];
}

// 查询符合条件的日记,同时关联用户表获取作者信息
final diaryResponse = await supabase
    .from('diaries')
    .select('''
      *,
      users(name, age)  // 关联users表,拉取作者姓名和年龄
    ''')
    // 排除当前用户屏蔽的日记
    .not('diaryId', 'in', '''
      (SELECT diaryId FROM block_diaries WHERE userId = '$currentUserId')
    ''')
    // 排除当前用户屏蔽的作者发布的日记
    .not('userId', 'in', '''
      (SELECT blocked_user_id FROM block_users WHERE blocker_user_id = '$currentUserId')
    ''')
    // 按创建时间倒序排列,最新的日记在前
    .order('createdAt', ascending: false);

// 解析结果(根据你的数据模型自行调整转换逻辑)
final List<Diary> diaries = diaryResponse.map((data) => Diary.fromJson(data)).toList();

方式二:使用LEFT JOIN过滤(性能更优)

当数据量较大时,左连接+IS NULL的方式性能优于子查询,原理是关联屏蔽表后,筛选出没有匹配到屏蔽记录的日记:

final currentUserId = supabase.auth.currentUser?.id;
if (currentUserId == null) {
  return [];
}

final diaryResponse = await supabase
    .from('diaries')
    .select('''
      *,
      users(name, age)
    ''')
    // 左连接block_diaries,匹配当前用户屏蔽的日记
    .leftJoin(
      'block_diaries',
      JoinFilter(
        'diaries.diaryId',
        'block_diaries.diaryId',
        additionalFilter: (query) => query.eq('block_diaries.userId', currentUserId),
      ),
    )
    // 左连接block_users,匹配当前用户屏蔽的作者
    .leftJoin(
      'block_users',
      JoinFilter(
        'diaries.userId',
        'block_users.blocked_user_id',
        additionalFilter: (query) => query.eq('block_users.blocker_user_id', currentUserId),
      ),
    )
    // 只保留没有匹配到屏蔽记录的日记(即未被屏蔽的)
    .isNull('block_diaries.diaryId')
    .isNull('block_users.blocked_user_id')
    .order('createdAt', ascending: false);

final List<Diary> diaries = diaryResponse.map((data) => Diary.fromJson(data)).toList();

关键注意事项

  • 字段名适配:如果你的block_users表字段不是blocker_user_id(屏蔽者)和blocked_user_id(被屏蔽者),请替换成实际业务中的字段名(比如userId和blockedUserId)。
  • 未登录边界处理:必须先判断当前用户是否登录,避免currentUserId为空导致查询报错。
  • 索引优化:给block_diaries表的(userId, diaryId)、block_users表的(blocker_user_id, blocked_user_id)创建复合索引,能大幅提升查询速度。
  • 分页支持:如果日记数量较多,可添加.range(startIndex, endIndex)实现分页加载,避免一次性拉取过多数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 06:17:24