Я решил поработать над системой уведомлений, вдохновившись другой статьей StackOverflow, в которой предлагалось отключить уведомление от основной части уведомления. Таким образом, у меня есть следующая схема:
notifications
id | user_id | notification_object_id | is_read
notification_objects
id | message | type
Я настроил его таким образом, чтобы я мог создать объект уведомления и отправить его нескольким пользователям в случае, если объект уведомления применяется к нескольким людям. Тип предназначен для того, чтобы объединять сообщения в одно уведомление по типу, что-то вроде того, как Facebook говорит: «Джон Доу, Джон Смит и 27 других пользователей прокомментировали …», вместо того, чтобы давать вам 29 отдельных уведомлений.
(Схема именования таблицы и столбца предназначена для CakePHP 3 «содержит»)
Что мне нужно, так это способ связать разных пользователей или объекты, которые будут играть роль в запросах. Пользователь, возможно, прокомментировал, поэтому мне, вероятно, понадобится user_id пользователя, который отправил сообщение, и мне нужно его где-то хранить.
Есть и другие случаи помимо пользователей; кто-то может захотеть узнать идентификатор комментария, чтобы он мог щелкнуть уведомление и сразу перейти к комментарию / 81. У меня есть много случаев, когда я хочу хранить различные типы идентификаторов, которые являются внешними ключами для других таблиц (пользователей, комментариев, статей и т. Д.), Для некоторых из которых могут потребоваться два внешних ключа (скажем, вы хотите упомянуть «Крис прокомментировал ваш статья «Как попросить StackOverflow о помощи» ») и укажите в уведомлении user_id для Криса и идентификатор статьи для статьи.
Каждый другой тип уведомления может иметь разные значения и таблицы, из которых он должен получать информацию. С чего начать при создании этой схемы?
Я попытаюсь ответить на этот вопрос с точки зрения ОО. Говоря в классы, не в таблицы, вы, вероятно, начали бы с чего-то вроде AbstractNotificationObject
класс с основными свойствами (дата, время, может быть сообщение) и несколько классов специализации, таких как NewCommentNotificationObject
с дополнительными свойствами (комментарий, комментирование пользователя) или NewFriendNotificationObject
, Переходя к схеме базы данных, вы можете применить один из типичных шаблонов ORM.
С помощью конкретность стола вероятно, не будет хорошей идеей, потому что это будет сводиться к отдельная таблица для каждого типа уведомлений (т.е. comment_notification_objects
стол и, может быть, еще много). Это не будет хорошо масштабироваться, и вы не сможете ссылаться на них из notification
таблица с использованием внешнего ключа. Кроме того, вы не сможете выбрать набор уведомлений разных типов с помощью одного запроса (без чего-то вроде UNION).
Наследование одной таблицы будет использовать только одна таблица со столбцом дискриминатора типов. Эта единственная таблица (давайте назовем это notification_objects
) необходимо будет содержать type
столбец, описывающий тип уведомления на самом деле (у вас это уже есть в вашей схеме). Вам также понадобятся столбцы для всех свойств, которые могут иметь специальные типы уведомлений (например, user_id
и comment_id
колонка).
+--------------+
| notification |
+--------------+
| id |
+--| object_id |
| +--------------+
|
| +-----------------------+
| | notification_objects |
| +-----------------------+
+->| id PK |
| date |
| type |
| user_id FK |--...
| comment_id FK |--...
| friend_id FK |--...
| [more fields to come] |
+-----------------------+
Pros:
Cons:
Я бы порекомендовал эту схему, если у вас есть набор типов уведомлений среднего размера, который не меняется регулярно.
Наследование таблиц классов где-то посередине; здесь вы бы создали центральный notification_objects
таблица и отдельные таблицы для каждого типа уведомлений (например, дополнительная comment_notification_object
стол с id
столбец (который, в свою очередь, является внешним ключом к notification_object
стол и user_id
а также column_id
:
+--------------+
| notification |
+--------------+
| id |
+--| object_id |
| +--------------+
|
| +----------------------+ +------------------------------+
| | notification_objects | | comment_notification_objects |
| +----------------------+ +------------------------------+
+->| id PK |<--+--| id PK/FK |
| date | | | comment_id FK |--...
| type | | | user_id FK |--...
+----------------------+ | +------------------------------+
|
| +--------------------------------+
| | newfriend_notification_objects |
| +--------------------------------+
+--| id PK/FK |
| friend_id FK |--...
+--------------------------------+
[more TABLES to come...]
Наследование таблиц классов также позволит вам запрашивать все уведомления одним запросом выбора. В зависимости от того, какой объем данных вам нужен, вам нужно добавить JOIN в соответствующие специализированные таблицы.
Pros:
Cons:
Я бы порекомендовал эту схему, если у вас много разных типов уведомлений или вы часто расширяете свою объектную модель и вам необходимо регулярно менять / добавлять новые типы уведомлений.
Ваш вопрос явно задан относительно реляционной схемы, поэтому я сосредоточился на этом. Если мыслить нестандартно, альтернативные решения могут включать:
Других решений пока нет …