Как мне разработать гибкую схему уведомлений MySQL, которая ссылается на несколько таблиц?

Я решил поработать над системой уведомлений, вдохновившись другой статьей 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 для Криса и идентификатор статьи для статьи.

Каждый другой тип уведомления может иметь разные значения и таблицы, из которых он должен получать информацию. С чего начать при создании этой схемы?

0

Решение

Я попытаюсь ответить на этот вопрос с точки зрения ОО. Говоря в классы, не в таблицы, вы, вероятно, начали бы с чего-то вроде 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:

  1. Загрузить все уведомления одним запросом
  2. Сохранять ссылочную целостность с внешними ключами

Cons:

  1. Плохо масштабируется (вам нужно будет добавить новые столбцы для каждого типа уведомлений)
  2. Таблица будет заполнена редко (многие столбцы будут пустыми)

Я бы порекомендовал эту схему, если у вас есть набор типов уведомлений среднего размера, который не меняется регулярно.

Наследование таблиц классов

Наследование таблиц классов где-то посередине; здесь вы бы создали центральный 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:

  1. Хорошо масштабируется / Добавляет новые типы без изменения существующей структуры
  2. Сохранять ссылочную целостность с внешними ключами

Cons:

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

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

За пределами реляционной коробки

Ваш вопрос явно задан относительно реляционной схемы, поэтому я сосредоточился на этом. Если мыслить нестандартно, альтернативные решения могут включать:

  • Бессистемные базы данных NoSQL
  • Системы обмена сообщениями, которые следуют архитектуре публикации / подписки
9

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]