2014-07-18 183 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中快速獲取樹,但您必須先學習基本知識。

相關問題