Лучший дизайн базы данных для системы обсуждения с различными типами категорий? - PullRequest
2 голосов
/ 09 сентября 2009

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

Допустим, у нас уже есть эти таблицы:

  • таблица пользователей с uid (PK)
  • таблица групп с гидом (ПК)
  • Таблица ассоциаций групп с gid (FK) и uid (FK)

Тогда, каков наилучший дизайн таблиц сообщений и сообщений для удовлетворения этих требований:

  • любой отдельный пользователь может отправить сообщение другому пользователю
  • любой отдельный пользователь может отправлять сообщения нескольким пользователям
  • любой отдельный пользователь может отправлять сообщения ВСЕМ пользователям в отдельной группе (количество пользователей в определенной группе может изменяться со временем)
  • вы должны иметь возможность запрашивать все сообщения, принадлежащие конкретному пользователю

Мое нынешнее мышление звучит так:

  1. Установите три таблицы:
    • сообщение с серединой (PK) и, скажем, темой
    • message_participants с mpmid (FK), mptype ENUM ('user', 'group') и mpid (FK из тип)
    • message_posts с msgmid (FK), ссылающимся на таблицу сообщений PK
  2. Чтобы получить все сообщения
    • получить все группы для определенного пользователя
    • запрос message_participants WHERE (mptype = 'user' AND mpid = uid) ИЛИ (mptype = 'group' И mpid IN (все пользовательские группы))

Таким образом, вы можете отправлять сообщения отдельным пользователям и группам одновременно.

Так вы обычно подходите к этому типу проблемы?

Ответы [ 2 ]

3 голосов
/ 10 сентября 2009

Джеймс прав в изложении ...

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

Перегрузка столбца внешнего ключа всегда плохой дизайн, который приводит к плохой целостности данных и другим проблемам.

Если ваша цель состоит в том, чтобы иметь «временных получателей» - то есть, если я присоединяюсь к группе сегодня, я сразу же вижу все сообщения этой группе со вчерашнего дня - тогда ваша модель близка. Описывать получателя как «участника» - плохая дикция, но я подойду к проблеме следующим образом ...

TABLE MessageRecipients
(
  Message_Id INT NOT NULL
    CONSTRAINT FK__MessagesRecipients__Messages
    FOREIGN KEY (Message_Id) REFERENCES Messages (Message_Id),

  RecipientType_Code CHAR(1) NOT NULL
    CONSTRAINT CK__MessageRecipients__RecipientType_Code_Domain
    CHECK RecipientType_Code IN ('U','G'),

  User_Id NULL
    CONSTRAINT FK__MessagesRecipients__Users
    FOREIGN KEY (User_Id) REFERENCES Users (User_Id),

  Group_Id NULL
    CONSTRAINT FK__MessagesRecipients__Groups
    FOREIGN KEY (Group_Id) REFERENCES Groups (Group_Id),

  CONSTRAINT CK__MessageRecipients__RecipientType_Validity
    CHECK (RecipientType_Code = 'U' AND User_Id IS NOT NULL AND Group_Id IS NULL)
       OR (RecipientType_Code = 'G' AND User_Id IS NULL AND Group_Id IS NOT NULL)

)

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

2 голосов
/ 10 сентября 2009

Это хороший вопрос. Похоже, вы на правильном пути. Вот мой подход:

Таблица:

  • сообщение с идентификатором, идентификатор_пользователя, тема
  • message_users с идентификатором (PK), message_id (FK), user_id (FK)
  • группы сообщений с идентификатором (PK), идентификатором сообщения (FK)

Теперь для примера: допустим, пользователь отправляет сообщение группе, вы вставляете одну строку в message_groups и вставляете одну строку для каждого члена группы в message_users. Это позволяет вам определить, какой группе (группам) было отправлено сообщение и какие пользователи получили сообщение в это время. Пользователи могут быть добавлены и удалены из групп в прошлом или будущем, поэтому вы должны записать каждого пользователя, который был в группе на момент отправки сообщения. Вы не можете просто записать группу.

Чтобы получить все сообщения для пользователя:

ВЫБРАТЬ * ОТ сообщения INNER JOIN message_users ON message.id = message_users.message_id WHERE message_users.user_id = {user_id}

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

Не знаю, зачем вам сообщения. У сообщений есть несколько постов? Надеюсь, это поможет.

...