2013-12-22 6 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

Я не следую - зачем вам нужно обновлять множество вхождений категории сразу? в том, что я предложил, у вас есть только одно вхождение категории в качестве документа, а дерево иерархии просто использует идентификатор категории, чтобы определить, кто его родители, возможно, более одного. – synhershko

+0

Единственное, что я вижу в этом как проблема, и, по общему признанию, это может быть только моя «новизна» к этому стилю, получает идентификатор определенной категории, как я могу получить всех своих детей? Это не позволяет вам запрашивать иерархию для получения идентификаторов этих детей, если вы не знаете путь до корня, и это также не позволяет вам получить этих родителей. Разве это не просто замена приоритета направления прохождения для другого - вниз против вверх? – MarqueIV

Смежные вопросы