我为用户创建了一个消息系统,它允许他们向另一个用户发送消息。如果这是他们第一次说话,则开始新的对话,如果不是,则继续旧的对话。
用户收件箱列出了用户与所有其他用户的所有对话,然后按其中包含最新帖子的对话排序。
一个用户只能与另一个用户进行一次对话。
当用户单击其中一个对话时,他们会被带到一个页面,该页面显示他们进行过的整个对话,最新帖子位于顶部。所以它有点像消息聊天功能。
我有两张桌子:
- 用户对话
- 用户留言
用户对话
包含一个自动增量 id,它是对话 id,以及 userId 和friendId。
发起第一个对话的人将始终是 userId 和接收者friendId,那么该对话将永远不会改变。
+----+--------+----------+
| id | userId | friendId |
+----+--------+----------+
用户留言
包含特定消息,以及读取标志、时间和会话 ID
+----+---------+--------+------+------+----------------+
| id | message | userId | read | time | conversationId |
+----+---------+--------+------+------+----------------+
这个怎么运作
当用户向另一个用户发送消息时,将运行查询以检查两个用户是否在 userconversation 表中具有匹配项,如果使用了匹配项conversationId
并继续对话,如果没有为他们创建具有唯一性的新行conversationId
。
复杂的地方
到目前为止一切都很好,但是在显示所有对话的消息收件箱时,按最新帖子排序,使用一个查询会变得很棘手。
为了能够列出对话,您必须首先找到每个对话的最新帖子,但是由于您不能在组之前排序,因此不可能对两个表进行一次查询,因此我必须使用以下内容:
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 以加快连接并提高数据完整性,因此我不能有两个自动增量行。
有没有另一种方法可以摆脱 userconversation 表并创建一个唯一的 Id 放入 conversationId 列?然后我可以将 userId 和friendId 移到 usermessages ...但这会产生很多冗余数据?