具有不同类别类型的讨论系统的最佳数据库设计?

时间:2009-09-09 17:22:34

标签: database-design messaging

我想为可能属于个人用户或用户组的邮件设计邮件收件箱表架构。

假设我们已经有了这些表格:

  • 使用uid(PK)的用户表
  • 使用gid(PK)对表进行分组
  • groups_association表,包含gid(FK)和uid(FK)

然后,满足这些要求的消息和消息发布表的最佳设计是什么:

  • 任何个人用户都可以向其他用户发送消息
  • 任何个人用户都可以向多个用户发送消息
  • 任何个人用户都可以向单个组中的所有用户发送消息(特定组中的用户数量可能会随时间变化)
  • 您应该能够查询属于特定用户的所有邮件

我目前的想法是:

  1. 设置三个表格:
    • 消息与mid(PK),让我们说主题
    • message_participants with mpmid(FK),mptype ENUM('user','group')和mpid(fK of the 型)
    • message_posts,其中msgmid(FK)引用消息表PK
  2. 获取所有消息
    • 获取特定用户的所有群组
    • query message_participants WHERE(mptype ='user'AND mpid = uid)OR(mptype ='group'AND mpid IN(所有用户组))
  3. 通过这种方式,您甚至可以同时向各个用户和群组发送消息。

    这是你通常会遇到这类问题的方法吗?

2 个答案:

答案 0 :(得分:3)

詹姆斯陈述......是正确的。

  

另外,请确保您不使用可引用多种主键的字段。 message_participants表中的mpid字段不应引用用户和组。

重载外键列总是设计不佳导致数据完整性差和其他问题。

如果您的目标是拥有“瞬态接收者” - 即,如果我今天加入某个群组,我会立即从昨天开始查看该群组的所有消息 - 然后您的模型就会关闭。将收件人描述为“参与者”是一种糟糕的用语,但我会按如下方式解决问题......

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)

)

否则,如果您希望将消息绑定到用户而不管组成员身份(例如,如果我删除一个组,我仍然会看到该组的消息),那么我会建议James的方法。

答案 1 :(得分:2)

这是一个很好的问题。听起来你走在正确的轨道上。这将是我的方法:

表:

    带有id,user_id,主题的
  • 消息
  • message_users ,ID为(PK),message_id(FK),user_id(FK)
  • 带有ID(PK)的
  • message_groups ,message_id(FK)

现在举个例子:假设用户向组发送消息,在message_groups中插入一行,并为该组的每个成员插入一行到message_users。这允许您捕获哪些组已发送消息以及当时哪些用户收到消息。可以在过去或将来从组中添加和删除用户,因此您必须记录发送邮件时组中的每个用户。只记录小组就无法逃脱。

获取用户的所有消息:

SELECT * FROM message INNER JOIN message_users ON message.id = message_users.message_id WHERE message_users.user_id = {user_id}

另外,请确保您不使用可引用多种主键的字段。 message_participants表中的mpid字段不应引用用户和组。

不确定为什么需要帖子。消息有多个帖子?希望这会有所帮助。