You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PostgreSQL双向用户屏蔽系统:如何实现正确的帖子可见性查询?

双向屏蔽机制下的帖子可见性SQL解决方案

你的问题核心是原查询用了INNER JOIN,导致用户没屏蔽任何人时查不到内容,而且只能拿到Block表有记录的用户帖子。咱们换个思路,先明确哪些用户的帖子是当前用户不能看的,然后排除这些,同时确保用户能看到自己的帖子,这样逻辑更清晰。

修正后的SQL语句

SELECT p.*
FROM Post p
WHERE p.user_id = @current_user_id
   OR p.user_id NOT IN (
       -- 找出当前用户主动屏蔽的人
       SELECT blocked_id 
       FROM Block 
       WHERE blocker_id = @current_user_id
       UNION
       -- 找出屏蔽了当前用户的人(双向屏蔽规则)
       SELECT blocker_id 
       FROM Block 
       WHERE blocked_id = @current_user_id
   );

逐行解释逻辑

  1. 优先显示自己的帖子p.user_id = @current_user_id 这部分保证用户不管有没有屏蔽别人,总能看到自己发的内容,这是最基础的需求。
  2. 构建屏蔽用户列表
    • 第一个子查询拿到当前用户主动屏蔽的所有用户ID;
    • 第二个子查询拿到所有屏蔽了当前用户的ID(因为是双向屏蔽,这些用户的内容也不能看);
    • UNION合并两个列表,去重后得到完整的“不可见用户”集合。
  3. 筛选可见帖子p.user_id NOT IN (...) 确保只显示不在屏蔽列表里的用户的帖子。

验证你的预期场景

  • 用户1(ID=1):屏蔽列表是用户2(主动屏蔽)+ 用户2(被屏蔽),排除用户2的帖子,最终看到自己和用户3的帖子,符合预期。
  • 用户2(ID=2):屏蔽列表是用户1(主动屏蔽)+ 用户1(被屏蔽),排除用户1的帖子,看到自己和用户3的帖子,符合预期。
  • 用户3(ID=3):Block表里没有涉及3的记录,所以屏蔽列表为空,NOT IN条件对所有用户都成立,加上自己的帖子,就能看到所有内容,完美符合需求。

可选的LEFT JOIN写法

如果你对NOT IN的行为不太放心(其实PostgreSQL里空集合的NOT IN会返回所有结果,完全没问题),也可以用LEFT JOIN来实现相同逻辑,可读性可能更好:

SELECT p.*
FROM Post p
-- 检查帖子作者是否被当前用户屏蔽
LEFT JOIN Block b1 ON p.user_id = b1.blocked_id AND b1.blocker_id = @current_user_id
-- 检查帖子作者是否屏蔽了当前用户
LEFT JOIN Block b2 ON p.user_id = b2.blocker_id AND b2.blocked_id = @current_user_id
WHERE p.user_id = @current_user_id
   -- 两个关联都没匹配上,说明没有双向屏蔽关系
   OR (b1.id IS NULL AND b2.id IS NULL);

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

火山引擎 最新活动