我应该如何设计用户阻止系统?

时间:2019-02-09 09:48:26

标签: postgresql database-design

我创建了一个小型社交网站,其中包含用户生成的内容。如果用户不喜欢自己发布的内容,他们应该可以选择互相阻止。

所以我使用的是postgresql,我有三个简单的表。

Table User
id (pk)  | user_name
1       | a
2       | b
3       | c

Table Post
id (pk)  | user_id (fk)
1       | 1
2       | 3
3       | 2
4       | 2

Table Block
id (pk) | blocker_id (fk)  | blocked_id (fk)
1       | 1              | 2
2       | 2              | 1

顺便说一句,如您所见,我使用双向阻止,因为我不希望如果user1阻止user2,则user2也不会看到user1的帖子。

我写了一条sql:

SELECT * FROM Post p INNER JOIN Block b
ON p.user_id = b.blocker_id
WHERE b.blocked_id <> @current_user_id

但是,如果用户没有阻止任何人该怎么办?该sql不涉及这种情况,它仅显示在 block 表中具有记录的用户帖子。

我期望的是

  • 对于user1,此sql应该返回user3和user1的帖子。
  • 对于user2,它应该返回user3和user2的帖子。
  • 对于user3,它应该返回每个用户帖子。

我该怎么做?

谢谢。

2 个答案:

答案 0 :(得分:2)

您想显示所有帖子,例如当前用户阻止的某个用户发布的帖子。使用NOT EXISTSNOT IN查找被阻止的用户:

SELECT * 
FROM post 
WHERE user_id not in (select blocked_id from block where blocker_id = @current_user_id);

答案 1 :(得分:2)

首先,我认为您使对称块对称的想法是错误的。想象一下,当user1阻塞user2时,这将在您的情况下在两个方向上创建两个块。如果user1决定取消阻止user2怎么办?在这种情况下,您将需要删除两个记录。但是,如果两个人都想互相阻挡怎么办?在这种情况下,您还将有两个记录。因此,畅通变得矛盾。我的建议是在user1阻止user2时创建一条记录,并同时搜索blocker_id和blocked_id,以便检查谁看不到谁的帖子如下:

select *
from User
join Block
on User.id = Block.blocker_id or User.id = Block.blocked_id

现在,让我们看看您的查询。您不需要加入Block,而是需要检查是否存在Block记录:

select *
from Post p
where p.user_id = @current_user_id and
      not exists (select id
                  from Block
                  where Block.blocker_id = p.user_id or Block.blocked_id = p.user_id)

请注意,我在PostgreSQL上工作不多(通常在SQL上工作很多),因此,如果我遇到一些语法错误,则可以将其归因于我在PostgreSQL中的无礼。

编辑

解决方案是以下代码:

select *
from Post p
where
not exists (select id
from Block
where ((Block.blocked_id = p.user_id) and (Block.blocker_id = @current_user_id)) or ((Block.blocked_id = @current_user_id) and (Block.blocker_id = p.user_id))

说明:我们需要找到当前用户阻止作者或作者阻止当前用户的阻止记录。