MySQL データベースに支えられた私の Web アプリケーションで、メッセージが複数のユーザー間の会話にグループ化されるメッセージング システムを提供したいと考えていますが、いくつかのニーズを満たすテーブル構造の設計に行き詰まっています。
- 複数のユーザーが 1 つの会話に参加できます
- ユーザーは会話に参加、閲覧、退出、削除できます
- 受信トレイ ビューで生成されるクエリはできるだけ少なくする必要があります
ここで、多対多リレーションの最初の要件は、ジャンクション テーブルを使用して解決できます。しかし、受信トレイ ビューの選択クエリを作成するときに、非常に多くの問題が発生することが証明されています。
2 番目の要件も課題であることが判明しました。ユーザーが会話を離れた場合でも、古いメッセージを読むことができるようにする必要があります。会話に残っているユーザー間の新しいメッセージは、去ったユーザーと共有しないでください。最初に考えたのは、会話に木のような構造を使用することでした。ユーザーが会話に参加または退出するたびに、親会話への参照を使用して新しい会話が作成され、ジャンクション テーブル内の残りの参加者との新しい関係が作成されます。
3 番目の要件も些細なことではないようです。受信トレイ ビューには、参加者として特定のユーザーとの会話のリストが表示されます。また、会話ごとに追加情報を表示する必要があります。現在の参加者全員の名前、会話への最後の返信、およびその返信の作成者です。受信トレイ ビューは、メッセージが属している会話に関する追加情報を含むメッセージのリストと考えてください。
私の現在のアプローチは次のようになります。
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`)
);
ここで壁にぶつかり、すべてのニーズを満たすソリューションが見つかりません。ここにいる誰かが、このデータベース設計にアプローチする方法についてアドバイスをくれるかもしれません。