【问题标题】:Best database design for a discussion system with varying category types?具有不同类别类型的讨论系统的最佳数据库设计?
【发布时间】:2009-09-09 17:22:34
【问题描述】:

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

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

  • 带有 uid (PK) 的用户表
  • 使用 gid (PK) 对表进行分组
  • groups_association 表与 gid (FK) 和 uid (FK)

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

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

我现在的想法是这样的:

  1. 设置三个表:
    • 消息中间(PK),让我们说主题
    • message_participants 带有 mpmid (FK)、mptype ENUM('user', 'group') 和 mpid (FK of the 类型)
    • message_posts 带有 msgmid (FK) 引用消息表 PK
  2. 获取所有消息
    • 获取特定用户的所有组
    • 查询 message_participants WHERE (mptype = 'user' AND mpid = uid) OR (mptype = 'group' AND mpid IN (所有用户组))

这样您甚至可以同时向单个用户和组发送消息。

这是您通常处理此类问题的方式吗?

【问题讨论】:

  • 为什么邮件属于用户组?为什么不直接复制消息并将其发送给组中的每个成员?您的请求是否声明消息必须属于一个组?只是好奇。
  • 好吧,如果我要向每个组成员发送一条单独的消息,那么如果该用户回复该消息,您将不得不将其发送给该组的所有成员,依此类推.因此,我在想必须有一种更好的方法可以只存储一个消息副本。我认为您可以有另一个表格将各个帖子与用户链接起来,该表格可以包含另一列关于该消息是否已被特定用户阅读或删除...

标签: database-design messaging


【解决方案1】:

詹姆斯的说法是正确的......

还要确保不要使用可以引用多种主键的字段。 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 的方法。

【讨论】:

  • 感谢 Alex,您的方法也值得考虑。正如我在上面的评论中提到的,我会坚持让新用户加入一个看不到旧消息的组...同意术语不是很简洁。
【解决方案2】:

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

表格:

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

现在举个例子:假设一个用户向一个组发送一条消息,您在 message_groups 中插入一行,然后在 message_users 中为该组的每个成员插入一行。这使您可以捕获当时向哪些组发送了消息以及哪些用户收到了消息。可以在过去或将来从组中添加和删除用户,因此您必须记录发送消息时组中的每个用户。只录制群组是不可能的。

获取用户的所有消息:

从消息中选择 * INNER JOIN message_users ON message.id = message_users.message_id WHERE message_users.user_id = {user_id}

还要确保不要使用可以引用多种主键的字段。 message_participants 表中的 mpid 字段不应同时引用用户和组。

不知道你为什么需要帖子。消息是否有多个帖子?希望这会有所帮助。

【讨论】:

  • 感谢您的回答。您没有对多个主键使用一列是正确的。您在创建消息时插入每个单独用户的方法是最初不想做的事情,但当我更多地考虑它时,这似乎是最合乎逻辑的事情,因为加入组的新用户不需要看到在他们加入群组之前创建的消息。我提到 POSTS 表是因为每条消息都可以对初始消息进行“参与者”评论。我想我应该称之为某种“讨论”......
猜你喜欢
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 2023-04-04
相关资源
最近更新 更多