我正在努力实现这里所解释的内容:
Creating a threaded private messaging system like facebook and gmail ,
但是我不完全理解乔尔布朗的回答。任何人都可以请解释一下。
这是我的数据库表与示例数据的样子(我假设我为了演示目的正确填写了它):
请帮忙!
谢谢
编辑 -> 继续
乔尔,这是正确的吗??
乔尔,我有点困惑,你能解释一下吗(评论/问题以粗体显示):
这里的想法是,每次用户启动一个全新的线程/消息时,它都会从 THREAD 表中的新记录开始。然后将用户添加为 THREAD_PARTICIPANT,并将消息的内容添加到 MESSAGE,MESSAGE 指向包含 THREAD。从 MESSAGE 到 USER 的 FK 表示消息的作者。
LoginId 1 向 LoginId2 发送消息 => 新记录插入到 MessageThread 表中。还将一条记录插入到 MessageThreadParticipant 记录,其中 MessageThreadId = 1,LoginId = 1(发件人)。并在 Message 表中插入一条新记录,MessageId =1,MessageThreadid =1,SenderLoginId = 1(正确??)
这就是我在迭代之后的内容:
我想我很困惑,因为 Loginid 2 无法知道有给他的消息。 ??或者我可能需要在 MessageThreadParticipant 中插入 2 条记录? (发送方和接收方)-> 这样双方都可以看到整个“对话”??
编辑2:
乔,我想我可以这样做:
SELECT
Message.MessageId, Message.CreateDate, Message.Body, Login.Username, Message.SenderLoginId
, (SELECT MessageReadState.ReadDate
FROM MessageReadState
WHERE MessageReadState.MessageId = Message.MessageId
) as ReadDate
FROM Message
INNER JOIN Login ON Message.SenderLoginId = Login.LoginId
INNER JOIN MessageThreadParticipant mtp on mtp.MessageThreadId = Message.MessageThreadId
AND ( Message.MessageId in
( SELECT Max(Message.MessageId)
FROM MessageThreadParticipant INNER JOIN Message
ON MessageThreadParticipant.MessageThreadId = Message.MessageThreadId
GROUP BY MessageThreadParticipant.MessageThreadId
)
)
Where mtp.LoginId = 2
ORDER BY Message.CreateDate DESC;
如果我错了,请纠正我:)
最佳答案
那你为什么不直接问? :)
让我试着确定我对你的要求的理解。在我看来,您正在查看一个线程,它是两个人之间消息的线性列表(不是树)。我认为您可能希望允许更多的人进入,而不仅仅是两个。这就像 Facebook 一样,只要有人发布一条消息,然后任意数量的人都可以阅读它,然后开始添加评论。当您添加评论时,它会将您置于话题中,并且您开始收到状态更新和电子邮件,告诉您话题中的事件等等。假设这就是您所追求的,那么我建议的架构 Big Mike不完全是你要找的。
请考虑以下情况:
这里的想法是,每次用户启动一个全新的线程/消息时,它都会从 THREAD 表中的新记录开始。然后将用户添加为 THREAD_PARTICIPANT,并将消息的内容添加到 MESSAGE,MESSAGE 指向包含 THREAD。从 MESSAGE 到 USER 的 FK 表示消息的作者。
当用户阅读消息时,他们会在 MESSAGE_READ_STATE 表中获得一个条目,以表明他们已将消息标记为已读,无论是显式还是隐式,具体取决于您的需求。
当有人对线程中的初始消息发表评论时,第二个 MESSAGE 会添加一个 FK 回到原始 THREAD,并且回复作者(用户)被添加到 THREAD_PARTICIPANT 表中。当消息由一个、两个甚至更多参与者添加到线程时,情况也是如此。
要获取任何线程中的最新消息,只需从 MESSAGE 中获取按创建日期(或身份 key )降序排序的前 1 条消息,其中消息 FK 发送到感兴趣的线程。
要获取用户最近更新的线程,请从按创建日期降序排序的消息中获取与前 1 项相关的线程,其中消息位于用户是 THREAD_PARTICIPANT 的线程中。
恐怕我永远无法在不打破 LinqPad 的情况下在 LINQ 中陈述这些事情。如果您无法理解上述内容,我可以用表定义和一些 SQL 来充实答案。只需在评论中提问。
编辑:要求和实现的澄清
明确要求:最初我考虑的是公开发布的消息,并有机会发表评论,而 Shane 则追求更多的直接消息功能。在这种情况下,初始接收者需要在一开始就包含在 THREAD_PARTICIPANT 表中。
为了清楚起见,让我们在表格中放置几行。这是场景,(为了纪念加拿大日):用户 1 向用户 2 发送 DM,询问 session 是否喝啤酒。用户 2 回答关于在哪里见面的问题,用户 1 回答。表格看起来像这样:(可能过于简化)
编辑 #2:访问 SQL 以获取线程中所有消息的列表,具有读取状态...
使用@OP 的模式,此 SQL 将获取给定线程中的消息列表,并指示给定用户是否已阅读每条消息。消息按最近的第一顺序排列。
SELECT
Message.MessageId
, Message.CreateDate
, Message.Body
, Login.Username
, (SELECT MessageReadState.ReadDate
FROM MessageReadState
WHERE MessageReadState.MessageId = Message.MessageId
and MessageReadState.LoginId = 2) as ReadState
FROM (Message INNER JOIN Login ON Message.SenderLoginId = Login.LoginId)
WHERE (((Message.MessageThreadId)=10))
ORDER BY Message.CreateDate DESC;
请注意,如果可以公平地称呼它,技巧是通过子选择获取读取状态。这是必要的,因为获取读取状态的部分标准需要外连接无法满足的 where 子句。因此,您可以使用子选择从 MessageReadState 子表中确定您想要的(可能缺少的)值。
编辑 3:SQL 用于获取给定用户的所有线程中的最新消息...
要获取给定用户参与的所有线程的列表,首先按最近的消息排序,只显示最近的消息(每个线程 1 条消息),然后您将使用与上述类似的查询,除了不是通过他们的 FK 过滤消息到感兴趣的线程,你通过一个子查询过滤消息,在感兴趣的用户参与的每个线程中找到最新的消息。 它看起来像这样:
SELECT
Message.MessageId
, Message.CreateDate
, Message.Body
, Login.Username
, (SELECT MessageReadState.ReadDate
FROM MessageReadState
WHERE MessageReadState.MessageId = Message.MessageId
and MessageReadState.LoginId = 2) AS ReadState
FROM Message INNER JOIN Login ON Message.SenderLoginId = Login.LoginId
WHERE ( Message.MessageId in
( SELECT Max(Message.MessageId)
FROM MessageThreadParticipant INNER JOIN Message
ON MessageThreadParticipant.MessageThreadId = Message.MessageThreadId
WHERE MessageThreadParticipant.LoginId=2
GROUP BY MessageThreadParticipant.MessageThreadId
)
)
ORDER BY Message.CreateDate DESC;
关于asp.net - 线程消息系统数据库架构设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6541302/