Как мне спроектировать систему блокировки пользователей? - PullRequest
0 голосов
/ 09 февраля 2019

Я создал небольшой социальный сайт, на котором есть пользовательский контент.И пользователи должны иметь возможность блокировать друг друга, если им не нравится то, что они публикуют.

Так что я использую 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 он должен возвращать каждые пользователи posts.

Как я могу это сделать?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Во-первых, я думаю, что ваша идея сделать блокировку симметричной неверна.Представьте себе случай, когда user1 блокирует user2, что в вашем случае создаст два блока в обоих направлениях.Что если user1 решит разблокировать user2?В этом случае вам нужно будет удалить две записи.Но что, если они оба хотели бы заблокировать друг друга?В этом случае у вас также будет две записи.Таким образом, разблокировка становится двойственной.Я предлагаю создать одну запись, когда user1 блокирует user2 и искать и blocker_id, и block_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.

EDIT

Решением является следующий код:

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))

Объяснение:Нам нужно найти записи блоков, где либо текущий пользователь блокирует автора, либо автор блокирует текущего пользователя.

0 голосов
/ 09 февраля 2019

Вы хотите показать все сообщения, кроме тех, которые опубликованы пользователем, заблокированным текущим пользователем.Используйте NOT EXISTS или NOT IN для поиска заблокированных пользователей:

SELECT * 
FROM post 
WHERE user_id not in (select blocked_id from block where blocker_id = @current_user_id);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...