ユーザー向けのメッセージングシステムを作成しました。これにより、ユーザーは別のユーザーにメッセージを送信できます。彼らが初めて話した場合は、新しい会話が開始されますが、そうでない場合は、古い会話が続行されます。
ユーザーの受信トレイには、ユーザーが他のすべてのユーザーと行ったすべての会話が一覧表示され、最新の投稿が含まれている会話の順に並べられます。
ユーザーは、別のユーザーと1つの会話しかできません。
ユーザーがこれらの会話の1つをクリックすると、最新の投稿が上部に表示された会話全体を表示するページに移動します。つまり、メッセージングチャット機能のようなものです。
私は2つのテーブルを持っています:
- ユーザー会話
- ユーザーメッセージ
ユーザー会話
userIdおよびfriendIdとともに、会話IDである自動増分IDが含まれます。
最初の会話を開始する人は常にuserIdと受信者のfriendIdになり、その会話でこれが変わることはありません。
+----+--------+----------+
| id | userId | friendId |
+----+--------+----------+
ユーザーメッセージ
読み取りフラグ、時間、conversationIdとともに、特定のメッセージが含まれます
+----+---------+--------+------+------+----------------+
| id | message | userId | read | time | conversationId |
+----+---------+--------+------+------+----------------+
使い方
ユーザーが別のユーザーにメッセージを送信すると、クエリが実行され、両方のユーザーがuserconversationテーブルに一致するかどうかが確認されます。一致する場合はそれconversationId
が使用され、会話が続行されます。一致しない場合は、一意の。を使用して新しい行が作成されますconversationId
。
複雑になるところ
これまでのところすべてが順調ですが、すべての会話のメッセージ受信ボックスを最新の投稿で並べ替えて表示する場合、1つのクエリで行うのは難しいです。
会話を一覧表示するには、最初に各会話の最新の投稿を見つける必要がありますが、グループの前に注文することはできないため、2つのテーブルで1つのクエリを実行することは不可能であるため、次を使用する必要があります。
SELECT
c.id,
c.userId,
c.friendId,
m2.message,
m2.read,
UNIX_TIMESTAMP(m2.time),
user1.username,
user2.username
FROM
(SELECT MAX(m1.id) AS MessageID
FROM usermessages m1
GROUP BY m1.conversationId) latest_msg
INNER JOIN usermessages m2 ON latest_msg.MessageID = m2.id
INNER JOIN userconversation c ON m2.conversationId = c.id
INNER JOIN user user1 ON c.userId = user.id
INNER JOIN user user2 ON c.friendId = user.id
WHERE c.userId = :userId OR c.friendId = :userId
ORDER BY m2.id DESC
LIMIT 10
これが最善の方法だとは思いませんが、他の方法も考えられませんか?
データベーステーブルはInnoDBであり、結合を高速化し、データの整合性を向上させるため、2つの自動インクリメント行を使用できません。
userconversationテーブルを削除し、conversationId列に配置する一意のIDを作成する別の方法はありますか?次に、userIdとfriendIdをusermessagesに移動するだけで済みます...しかし、これにより多くの冗長データが作成されますか?