2014-07-18 184 views
1

我正在编写我的第一个Web应用程序,我使用Postgres来存储数据。如何在PostgreSQL中存储多个收件人的邮件?

我想实现以下功能:具有多个收件人的邮件。最理想的情况是,也有很好的线程支持。基本上,我想要像线程的电子邮件,但在我自己的应用程序。

我是RDBMS的新手,所以我没有想到组织表格的最佳方法。我如何存储这种多对多的关系?

回答

2

您需要:

  • 为您的应用程序的用户,与通常的列(唯一idname等)的表,

  • 的消息表,其中也有独特的id,以及一列来指示它回复哪个消息;这会让你建立线程

  • 构成了多对多的关系,与用户表,并在消息表的外键外键的第三个表,

获取所有收件人对于一个给定的消息,或者给定接收者的所有消息只是在所有三个表之间进行一些内部连接以及正确的where子句。

对于线程,您需要一个递归公用表表达式,它可以跟踪消息表中的行之间的链接。

喜欢的东西:

WITH RECURSIVE threads AS (
    SELECT id, parent_id, id AS root_id, body 
    FROM messages 
    WHERE parent_id IS NULL 
    UNION ALL 
    SELECT msg.id AS id , msg.parent_id AS parent_id, msgp.root_id AS root_id, msg.body AS body 
    FROM messages AS msg 
    INNER JOIN threads AS msgp 
    ON (msg.parent_id = msgp.id) 
) 
SELECT * 
FROM threads 
WHERE root_id = :root; 

凡列root_id包含行ID在当前行线的起源,会让你选择一个线程,其root_id由参数设置:root

多个收件人,你需要做的内连接上threads

WITH ... 
) 
SELECT * 
FROM threads 
INNER JOIN threads_users tu 
ON threads.id = tu.msg_id 
INNER JOIN users 
ON users.id = tu.user_id 
WHERE root_id=:root 
+1

你的答案是技术上是正确的,但在我看来,错误的方向引导。你的查询正在加载所有的消息,所以'select * from messages'会做同样的事情,还是我错了?你也假设他想装载整个子树。如果这是真的,他可能会加载整个线程,在这种情况下,thread_id会更加高效。正如我在答案中所写的:RDBM中的树是一个棘手的话题。您应该选择最简单的解决方案,然后 - 如果需要 - 选择适合您需求的实施方案。 – Achim

+0

@Achim,感谢您的输入!确实,查询结果是非常简单的,我只是演示了用于查询嵌入树结构的表中的线程的机制。我会尝试使用相同的基本原则以更好,更准确的示例更新我的答案。 – didierc

3

有关于如何将数据结构映射到关系模型的整本书,所以我的答案只是第一个非常简单的提示。我们称之为“默认情况”:

您通常会为您的邮件(一行=一条邮件)和一个收件人(一行=一个收件人)设置一个表。两者都必须有一些唯一的关键字,通常是一个称为id的列,它具有唯一的整数。

您连接(或关联;-))这两个表与第三个表。这个只有两列,包含消息的ID和收件人的ID。所以每个消息接收者关系都有一行。这就是所谓的m:n关系。

消息的线程是1:m的关系。一条消息可以有多个孩子,但每条消息只能有一个父代。因此,您不需要邮件收件人表中的“中间表”。您可以将父消息的标识存储在消息表中。

为了让你意识到这一点:RDBMS并不是真正为这种类似于消息线程的结构树而制作的。刚开始时,这可能是一个令人沮丧的第一个例子。即使它工作,对于不重要的数据量也会很慢。有一些解决方案可以在SQL中快速获取树,但您必须先学习基本知识。

相关问题