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

Столбцы таблицы подписки:

id(integer, AI)
type('String, can be 'article', 'comment', 'user')
ref('integer', indicates the index key to an external table)
user_id('integer', foreign key to the users table)

Таким образом, эта строка будет пользователем с id = 101, который подписан на комментарий с id 99.

1 | comment | 99 | 101

Пользователь с id = 101 также подписан на статью с id = 88

1 | article | 88 | 101

Вы уловили идею. Это хороший дизайн?

1
user3127415 24 Дек 2013 в 14:48

2 ответа

Лучший ответ

Я бы избегал этого подхода из-за элемента «волшебная строка». Ваши запросы должны будут полагаться на чтение строки, чтобы решить, подписан ли пользователь на что-то.

Я бы подумал о том, чтобы использовать другой подход и иметь таблицу, которая просто представляет пользователя, а затем иметь таблицы «ссылок» для сопоставления пользователей (по их идентификатору) с подписями определенного типа.

Например:

 Users                UsersInArticles              Articles
 -----------          ----------------             ----------
 UserID               UserID                       ArticleID
 Name                 ArticleID                    Title
 Address                                           Body
 etc...                                            etc..

Таблица UsersInArticles представляет пользователя (по идентификатору пользователя), который подписан на конкретную статью (по идентификатору статьи).

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

Кроме того, здесь нет никаких волшебных нитей.

При таком подходе, чтобы найти всех пользователей, подписанных на статью (например, на статью 123), вы можете просто выполнить следующий запрос (вместо сравнения со строковым столбцом, чтобы найти «Статью» и т. Д.).

SELECT UserID from UsersInArticles WHERE ArticleID = 123

Я также подозреваю, что эта схема позволит выполнять запросы быстрее, чем столбец varchar, представляющий тип подписки.

0
Dave S 24 Дек 2013 в 12:41

Это хороший дизайн?

Нет.

СУБД не может обеспечить для вас ссылочную целостность (через внешние ключи). А в параллельной среде реализовать ссылочную целостность вручную на удивление сложно, чтобы сделать правильно (без условий гонки) и с хорошей производительностью.

Вместо этого вы можете просто использовать несколько таблиц подписки (по одной для каждого типа «подписываемого» элемента). Или, если вы хотите избежать увеличения числа таблиц, используйте несколько FK или наследование, как this (но вам не обязательно для обеспечения исключительности FK).

0
Community 23 Май 2017 в 11:56