【发布时间】:2013-08-20 16:54:03
【问题描述】:
在我的由 MySQL 数据库支持的 Web 应用程序中,我想提供一个消息传递系统,其中消息被分组到多个用户之间的对话中,但我坚持设计一个满足我的一些需求的表结构:
- 多个用户可以参与一个对话
- 用户可以加入、阅读、离开和删除对话
- 收件箱视图应生成尽可能少的查询
现在,多对多关系的第一个要求可以通过使用联结表来解决。但事实证明,在为收件箱视图编写选择查询时会产生很多问题。
第二个要求也被证明是一个挑战。如果用户离开对话,他应该仍然可以阅读旧消息。对话中剩余用户之间的新消息不应与离开的用户共享。我首先考虑使用树状结构进行对话。每次用户加入或离开对话时,都会创建一个引用父对话的新对话,并创建与联结表中剩余参与者的新关系。
第三个要求似乎也不是微不足道的。收件箱视图应显示与特定用户作为参与者的对话列表。此外,应为每个对话显示附加信息:所有当前参与者的姓名、对话的最后回复和回复的作者。将收件箱视图视为包含有关其所属对话的附加信息的邮件列表。
我目前的做法是这样的:
CREATE TABLE `conversation` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parentId` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `parentId` (`parentId`),
CONSTRAINT `conversation_ibfk_1` FOREIGN KEY (`parentId`) REFERENCES `conversation` (`id`)
);
CREATE TABLE `participant` (
`userId` int(11) unsigned NOT NULL,
`conversationId` int(11) unsigned NOT NULL,
`readAt` datetime DEFAULT NULL,
PRIMARY KEY (`userId`,`conversationId`),
KEY `conversationId` (`conversationId`),
CONSTRAINT `participant_ibfk_2` FOREIGN KEY (`conversationId`) REFERENCES `conversation` (`id`),
CONSTRAINT `participant_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`)
);
CREATE TABLE `reply` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`conversationId` int(11) unsigned NOT NULL,
`userId` int(11) unsigned NOT NULL,
`text` text NOT NULL,
PRIMARY KEY (`id`),
KEY `conversationId` (`conversationId`),
KEY `userId` (`userId`),
CONSTRAINT `reply_ibfk_2` FOREIGN KEY (`userId`) REFERENCES `user` (`id`),
CONSTRAINT `reply_ibfk_1` FOREIGN KEY (`conversationId`) REFERENCES `conversation` (`id`)
);
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
);
我在这里碰壁了,找不到满足我所有需求的解决方案。也许这里有人可以就如何处理这种数据库设计给我一些建议。
【问题讨论】:
-
第二个要求:添加一个布尔列
Active。当用户离开对话时,将其设置为0 -
另外,您的表中似乎缺少时间戳。这些有助于确定最新回复以及显示该回复的时间。
-
感谢您到目前为止的回复。当前的设计还不是最终的。将包括 createdAt 和 updatedAt 时间戳。目前,我仍在尝试让整个系统在理论上运行。不幸的是,添加一个布尔标志并不能解决问题,因为只有在用户离开对话之前的消息应该与他共享。因此,用户必须从对话中删除,但他应该仍然能够阅读旧消息。
-
您将只包括标志为
1的参与者。或者,您可以在人们加入/离开时填充另一个表(时间戳、对话 ID 和用户 ID)。然后,如果它们存在于此表中,则仅显示时间戳之前的对话。 -
@Philipp 为什么不看看 EJabberd 数据库,它是一个开源消息传递系统,您可以下载并安装它。我已经用 10 000 000 个用户 + 网络运行了这个数据库,它运行得非常好。可能会回答几个问题,然后再提出几个问题。
标签: sql database-design structure message create-table