如何在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
相关产品推荐
相关产品推荐

