2013-12-22 69 views
0

在RavenDb中,我必須存儲分層數據,我需要遞歸查詢它。表現是這裏最大的擔憂。在RavenDb中建模分層數據

我有類似以下之一:

public class Category 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public Category Parent { get; set; } 
} 

在這種情況下,如果我存儲在文檔本身內部的父類,它將對我來說很難管理,因爲我會複製數據分類遍佈各地。

因此,爲了那麼容易,我可以按照以下存儲這樣的:

public class Category 
{ 
    public int Id { get; set; } 
    public int? ParentId { get; set; } 
    public string Name { get; set; } 
} 

但在這種情況下,我不知道性能怎麼會在這裏,我將有幾百萬的記錄,我需要從此引用創建類別樹。

RavenDb在性能是最大的擔憂時如何建模這種類型的數據是否存在某種決定?

回答

4

層次結構通常在定義層次結構的一個文檔中進行最佳建模。在你的情況下,可以定義分類樹,類別本身可以由獨立文檔表示(因此可以包含名稱,描述等,並允許其他集合引用它們),或者不是。

從代碼建模的類文件將是這個樣子:

public class Category 
{ 
    public string Id { get; set; } 
    public string Name { get; set; } 
    // other meta-data that you want to store per category, like image etc 
} 

而且層次樹文檔可以從類似下面的類,在這個類可以有它使節點容易的方法進行序列化訪問:

public class CategoriesHierarchyTree 
{ 
    public class Node 
    { 
     public string CategoryId { get; set; } 
     public List<Node> Children { get; set; } 
    } 

    public List<Node> RootCategories { get; private set; } 

    // various methods for looking up and updating tree structure 
} 

層次樹的這種做法有幾個重要的優點:

  1. 一個事務範圍 - 當樹更改時,樹總是在一個事務中更改。您不能受到樹的多個併發更改的影響,因爲您可以在編輯此文檔時利用樂觀併發。使用你提出的方法是不可能保證的,因此很難保證隨着時間的推移層次結構樹的完整性和正確性。如果您將層次結構視爲樹,則每次更改都會鎖定整個樹,直到完成爲止。層次樹是一個實體。
  2. 緩存 - 即使使用主動緩存,可以快速高效地緩存整個層次結構,從而最大限度地減少服務器在層次結構上的查詢訪問次數。
  3. 所有操作都完全在內存中完成 - 因爲它的一個文檔,也就是對象,層次結構上的所有查詢(其子對象列表的父對象)都完全在內存中,並且實際上成本接近於無法執行。與Recurse()一起使用索引來回答這樣的查詢的成本是數量級的(網絡成本和計算)。你提到性能是最大的擔憂 - 所以這是一個勝利者。
  4. 每個類別有多個父母,沒有非規範化 - 如果類別文檔被保存在層次結構樹之外,就像上面演示的那樣,您可以有效地將一個類別放在多個父母下,而不需要非規範化。所有類別數據都在一個位置,位於樹之外的文檔中,樹只保存對該類別的引用。

我強烈推薦使用這種方法。這是從關係思維模式轉變過來的,但它的價值如此之大,即使樹木變大了。

+0

謝謝!這真的有幫助。在這種情況下,我會在多個地方複製一個類別(可能有1000次,誰知道)。那麼,在RavenDb中,有沒有辦法在多個地方更新類別信息呢?或者我應該逐一找到它們並單獨更新它們?我在這裏查看批量更新(http://ravendb.net/docs/2.0/client-api/set-based-operations),但不確定這是否是我需要的。 – tugberk

+0

我不關注 - 爲什麼您需要一次更新多個類別的事件?在我所建議的內容中,只有一個類別作爲文檔出現,層次結構樹只是使用類別ID來定義誰是其父母 - 可能有多個。 – synhershko

+0

我認爲這是一個問題,無可否認,這可能只是我對這種風格的「新鮮感」,給予了特定類別的ID,我怎樣才能得到它的所有孩子?這不會讓您查詢層次結構以獲取這些兒童的ID,除非您知道該路徑一直回到根目錄,並且這也不容易讓您獲得這些父母。這不僅僅是交換一個穿越方向對另一個方向的優先級 - 向下還是向上? – MarqueIV