2013-02-01 87 views
1

首先,我承認我是DDD的新手,需要閱讀「blue book」。DDD - 聚合根 - 處理效率和併發

我正在構建一個具有「Match」類型的AggregateRoot的系統。每個Match可以包含「投票」的集合,並且具有隻讀的「VoteCount」屬性,當用戶對Match進行投票或反對投票時,該屬性會增加。

由於許多用戶可能同時在Match上進行投票,因此必須將Vote添加到匹配中,並且VoteCount必須作爲一個涉及寫入鎖的原子操作增加/減少(鎖由D B)。 (我需要VoteCount作爲數據庫中的一個靜態值,以便由其他進程/組件有效查詢)。

在我看來,如果我堅持嚴格的DDD,那麼我將編碼此操作:

應用服務會收到一個投票請求對象 服務會從Match Repository中檢索Match對象 然後服務會調用Match對象上的某種方法來添加投票到集合並更新VoteCount。 資源庫,然後將堅持那場比賽的實例回到DB 然而,這種方法是不是我的2個主要原因應用是可行的,因爲我看到:

我使用的是後端的MongoDB,並不能完成這個讀 - 將操作寫入事務以防止對Match數據及其相關投票和VoteCount的髒讀。

效率非常低。我拉回整個對象圖只是爲了添加投票並增加VoteCount。雖然這在文檔數據庫中比在關係數據庫中更有效,但我仍在執行不必要的讀取操作。

問題1 & 2將單個Vote對象發送到存儲庫並對Mongo執行一條原子更新語句時不會出現問題。

可能投票,在這種情況下被視爲一個「聚合」,並應該得到自己的存儲庫和聚合狀態?

回答

1

可能投票,在這種情況下被認爲是一個「聚合」和值得 自己的存儲庫和聚合狀態?

我想這可能是正確的答案。聚合應該是事務一致性邊界。比賽中的選票之間是否存在一致性要求? Match集合上的投票集合的呈現將暗示存在。然而,似乎一票與下一票無關。

相反,我會分別存儲每個投票。通過這種方式,您可以使用MongoDB的聚合功能來獲取計數,但我不確定它是否仍然很慢。如果是,則可以使用Map/Reduce功能進行聚合。

更一般地說,這可能不是DDD的最佳選擇。如果域名不是由複雜的行爲組成,那麼幾乎沒有理由嘗試將DDD戰術模式(實體,agreggate)調整到該域名。

+0

謝謝!然而,如果我「正常化」數據,將Votes和Matches存儲爲單獨的集合,那麼我將無法將它們「加入」到單個查詢中,是否正確?我必須循環縮小投票結果並獲得關聯的匹配? – drogon

+0

Vernon關於聚合設計的鏈接(http://dddcommunity.org/library/vernon_2011/)已經真正解決了問題。感謝您的鏈接(來自其他職位)和這個答案。再次感謝! – drogon

1

是的,你可以模型投票作爲一個聚合本身。在現實世界中,人們通常會一次投幾個東西。然後這個合計將被稱爲投票而不是投票。您只有一個特殊情況,即一次只能投票一個項目。

我不能MongoDB的說話(也許別人可以) - 但你將有一個非常輕鬆的時刻,RavenDB的東西像這樣:

public class Match 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } // or whatever 
} 

public class Vote 
{ 
    public string Id { get; set; } 
    public string MatchId { get; set; } 
    public string UserId { get; set; } 
    public bool YeaOrNay { get; set; } // or whatever 
} 

然後你只建立一個地圖/減少索引你的選票來計算結果。

+0

謝謝,馬特。對於Mongo,我還是個新手,對於如何將查詢和投票集合組合成一個結果集,類似於SQL中的聯接,仍然有一些未解決的問題,而沒有遇到n + 1問題。 – drogon