2014-05-14 42 views
2

我正在將我的應用程序從關係數據庫移動到物化/谷歌應用程序引擎。使用物化多對多關係?

的應用具有如下建模的關係:

一個Message可以被髮送到許多Users。每User可以有許多Message發給他們。

我需要能夠掃描發往特定User的所有Message

我如何用Objectify做到這一點?

回答

4

有很多方法可以做到這一點。

  1. 您可以保存用戶對象中的消息列表。這將很好地滿足您的要求,以便將所有消息發送給用戶,因爲不需要執行查詢。

  2. 您可以保存消息對象中的用戶列表。要獲取發送給單個用戶的所有消息,請執行查詢。

  3. 你可以保存上面的兩個列表。請記住,在App Engine中通常不需要規範化並擔心磁盤空間和重複。幾乎總是建立你的結構,以便查詢速度很快。

  4. 您可以忘記列表,並且可以像關係數據庫中的表一樣擁有關係對象。在一些使用情況下,它仍然是App Engine中不錯的選擇,例如當列表太大(數千)時,並且會膨脹對象,甚至可能無法進行查詢。

,這將決定採取關係到您指定的查詢哪種方式最重要的變量,是多少郵件通常會涉及到單個用戶,以及是否會有消息的最大值是多少?如果我們談論的是平均數十甚至更少的數字,那麼用戶對象中的消息列表聽起來像是一個很好的選擇。如果我們正在談論更多,尤其是如果無限制的話,那麼它將不會如此出色,並且您將需要進行實際的查詢。

+1

+1,這裏的關鍵是改變對'消息'的看法:在RDBMS中,你會將你的消息視爲絕對的「信息片段「你通過查詢連接到用戶。通過數據存儲,用戶擁有郵件副本,如電子郵件:使用您的Gmail帳戶,您不關心發件人在發送郵件後是否會將其刪除,一旦您收到電子郵件,您實際上「擁有」了一份副本即與發件人斷開連接。要「發送」一個「消息」,你必須在發送者「發送」籃子和收件人「收件箱」籃子中實際添加一個副本。 –

1

你必須保持你自己的關係。這是因爲根據應用程序的不同,讓用戶不需要消息,甚至相反就可以存在。

通過物化維基建議的方法(https://code.google.com/p/objectify-appengine/wiki/IntroductionToObjectify多值關係)是保持鍵

public class Message 
{ 
    @Id String timeStamp; 
    Key<User>[] destination; 
} 

public class User 
{ 
    @Id String name; 
    Key<Message>[] inbox; 
} 

的集合(或陣列),那麼如果你想,當用戶刪除刪除所有用戶的消息,只需在用戶面前將其從數據存儲中刪除即可。如果您想爲特定用戶添加新消息,也完全一樣。

3

超越的答案已經發布,我建議你包括從用戶到消息中的鏈接,原因有三:在GAE

  • 集合被硬限制到5000項。只要用戶的收件箱超過5k項,您的應用就會開始拋出異常。

  • 擴展實體中的數據量會帶來性能成本;加載一堆500k實體比加載一堆5k實體要慢。加上你對memcache的使用將不太有效,因爲你可以在同一個空間中容納更少的項目。用戶對象傾向於加載lot

  • 您可以輕鬆達到單個實體(1/s)的交易利率限制。如果有50人同時向你發送消息,你將會遇到大量的併發問題,因爲所有50人都會以樂觀的失敗重試。

如果你可以用5000個收件人單個郵件限制居住,存儲設定目的地密鑰的消息(和索引這一套,所以你可以查詢用戶的所有消息)可能是一個很棒的解決將消息分配給發件人的@Parent幾乎肯定也有好處。

如果您是類似twitter的人,並且希望消息具有超過5k個收件人,或者您的郵件通常有很多收件人(因此郵件實體臃腫),則您可能需要考慮關係索引實體模式Brett Slatkin在他2009年的Google I/O談話中談到:https://www.youtube.com/watch?v=AgaL6NGpkB8

+0

感謝您的提示。我預計每封郵件少於5000個收件人。但是,我怎樣才能讓消息成爲發件人的父母?你不是這個意思嗎?因爲一旦有人創建了一條消息,它將永遠來自他們,不能從其他任何人那裏「出來」。 – mdarwin

+0

看來,如果項目超過5000,創建另一個實體來存儲關係是最好的解決方案(這就像關係數據庫映射表一樣) –