2016-03-08 35 views
0

我正在爲我的移動應用程序提供通知訂閱源,並且正在尋找關於某個問題的一些幫助。在GAE中創建通知類型訂閱源Objectify

該應用程序是一個Twitter/Facebook類似的應用程序,用戶可以發佈狀態,其他用戶可以喜歡,評論或訂閱他們。

我想要在我的應用程序中有一件事是讓用戶可以看到誰喜歡/評論他們的帖子或訂閱他們。

這個系統的第一部分我發現,當一個用戶喜歡/評論/訂閱時,一個Notification實體將被寫入數據存儲,並提供關於該事件的詳細信息。要顯示用戶Notification的所有我需要做的是查詢該用戶的所有Notification,按日期創建desc進行排序,並且我們有其他用戶對特定用戶帳戶採取的操作的一個很好的小動作。

我遇到的問題是有人不喜歡帖子,取消訂閱或刪除評論時該怎麼做。目前,如果我要查詢該特定通知,則可能會由於最終一致性而從數據存儲區返回任何內容。我們可以想象有人喜歡,然後立即不喜歡一個職位(沒有這樣做的B/C?= P)。發現Notification的查詢可能會返回null,並且在調用ofy().delete().entity(notification).now();時沒有任何內容會被刪除。現在用戶在Feed中有一個通知,說Sally喜歡他的帖子,但實際上她喜歡,然後很快就不喜歡它了!

在這整個系統中的扳手的是,我不能Key<Notification>刪除,因爲我真的沒有辦法知道Notificationid試圖刪除它時。

我正在試驗的潛在解決方案是不刪除任何Notification s。相反,我會一直寫Notification's,並簡單地指出通知是正面還是負面。然後在我的查詢中向特定用戶顯示通知,我可以以某種方式顯示總和爲正的Notification。這也會在數據存儲上節省一些錢,因爲刪除實體很昂貴。

+0

以及快速連續的喜好和取消頂你可以簡單地抖在客戶端上的行動,等待+/- 5秒鐘,直到結果趨於穩定,然後,只然後,將請求發送到服務器以執行實際的類似/不多於類似的持久性操作。 – konqi

+0

@konqi好主意。仍然希望這個API系統堅實! – Micro

+0

這同樣適用於服務器端,但可能需要一些memcache和任務隊列。或者你可以添加鎖定,比如說:如果你喜歡一個通知,你可以持續10秒,但是你需要的只是一個時間戳(也可能是一些memcache)。這也會減少你的數據存儲寫入... – konqi

回答

1

有我以前就解決了這個問題,有三種主要方式:

  1. 確定性的關鍵

    例如

{用戶ID} - {後的ID} - {贊} by likes

{user-id} - {post-id} - {comment-by} - {comment-index}評論

這將適用於您定義的問題的大多數基本用例,但您會發現一些有毛的邊緣案例(例如管理註釋的索引,因爲它們會被編輯和刪除)。這將允許獲得和刪除鍵

  • 並行數據結構
  • 這裏的想法是在事務的時間來建立一個以上的實體,而是使確定他們有相關的鑰匙。例如,當某人對某個訂閱源項目發表評論時,創建一個評論實體,然後創建一個具有相同ID的CommentedOn實體,但使其具有該評論者用戶的父密鑰。

    然後,您可以對CommentedOn進行強烈一致的查詢,並使用相同的ID在註釋上執行get by鍵。如果太難了,你也可以只存儲一個密鑰,而不是有匹配的ID。每次我做到這一點時,在實踐中使用匹配的ID更容易。

    這種方法的主要侷限性在於,您自己有效地創建了一個索引,並且可以在需要的時候爲您提供強大一致的查詢,但事務性寫入的吞吐量限制可能變得難以理解。您還需要仔細管理狀態更改(如刪除)。

  • 國家對實體
  • 假設通知對象標誌只是表明發生了什麼事情,但鏈接到實際數據的另一個實體,你可以存儲的狀態標誌用戶(刪除,隱藏,私人等)在該實體。然後列出您的通知將是加載實體服務器端和過濾代碼(或可能後續過濾的查詢)的問題。

    在一天結束時,解決方案的複雜性應該反映問題的複雜性。我會從方法3開始,然後在理解更全面的需求時遷移到方法2。這是一種更加健壯和靈活的方法,但XG交易限制的複雜性將會超越它的頭 - 但最終像這樣的分佈式饋送是一個難題。

    +0

    謝謝分享!你給了我一些新的想法,我可以肯定地在這裏使用。我喜歡方法3,方法2是我從未想過要做的事情。 – Micro

    +0

    您提到的交易限制是什麼? – Micro

    +0

    XG事務僅限於25個根實體關鍵字,對於根實體而言,記錄的吞吐量限制爲1 /秒(實際上可能爲5個/秒左右)。並行數據結構使用更多的根實體來實現強一致的查詢,但其他併發事務(例如在同一秒內)可能只使用其中一個實體,但與其他實體結合使用。對於僅通過影響相同根實體而耦合的不同XG事務的吞吐量特性沒有明確定義。 – Nick

    0

    我結束了做什麼工作了我的具體型號是創建一個Notification實體之前,我會先分配和它ID:

    // Allocate an ID for a Notification 
    final Key<Notification> notificationKey = factory().allocateId(Notification.class); 
    final Long notificationId = notificationKey.getId(); 
    

    然後創建我LikeFollow實體的時候,我會設置屬性Like.notificationId = notificationId;Follow.notificationId = notificationId;

    然後,我會保存兩個實體。

    後來,當我要刪除LikeFollow我可以這樣做,並在同一時間獲得Notification的標識,裝載Notification通過密鑰(這是十分一致的這樣做),並刪除它太。

    只是另一種方法,可以幫助別人= d

    +0

    將notificationId存儲爲Ref <>可能更爲方便,這樣可以更容易地處理一般情況,並且具有編碼完整密鑰的優勢,而不僅僅是一個ID,如果您需要在路上更改父級密鑰層次結構。這可以讓您避免完整的數據遷移。它們在數據存儲區瀏覽器中也可以更好地工作,因爲數據存儲區鍵是第一類類型。 – Nick