Моделирование иерархических данных - GAE - PullRequest
5 голосов
/ 01 сентября 2010

Я новичок в google-app-engine и в хранилище данных Google (bigtable), и у меня есть некоторые сомнения относительно того, какой из них может быть лучшим подходом для разработки необходимой модели данных.

Мне нужносоздайте модель иерархии, что-то вроде каталога товаров, каждый домен имеет несколько поддоменов в глубине.На данный момент структура продуктов меняется меньше, чем прочитанные требования.Пример вина:

  • Происхождение (Тоскана, Приорат, Эльзас)
  • Винодельня (принадлежит только одному Происхождению)
  • Вино (Принадлежит только одному Винзаводу)

Все отношения являются непересекающимися и неполными.Кроме того, в порядке требований, вероятно, нам нужно хранить счетчики использования для каждого вина (могут потребоваться транзакции)

В порядке документации, кажется, есть различные потенциальные решения:

  • Управление предками.Использование родительских отношений и транзакций
  • Управление псевдо-предками.Имитация предков с помощью db.ListProperty (db.Key)
  • ReferenceProperty.Явное указание связи между классами

Но в порядке ожидаемых запросов на получение вин ... иногда по сортам, иногда по происхождению, иногда по винодельне ... меня беспокоит поведениезапросов, использующих эти структуры (например, множественные объединения в реляционной модели. Если вы запрашиваете продукты семейства ... вам нужно присоединиться к окончательному глубокому квалификатору в дереве продуктов и присоединиться начиная с семейства)

Может быть, лучше создать дублированную информацию (в порядке рекомендаций команды Google: операции стоят дорого, а хранилище нет, поэтому дублирующийся контент не должен рассматриваться как главная проблема)

Некоторые ответыдругие подобные вопросы предлагают:

  • Сохранить все родительские идентификаторы в виде иерархии в строке ... как свойство пути
  • Дублировать отношения между сущностью Drink и всеми родителями вдерево ...

Есть предложения?


Привет, Уилл,

В нашем случае более строгий иерархический подход, как вы представляете во втором примере.И запросы для получения списка продуктов, получить только один не обычно.

Нам нужно извлечь все вина из Происхождения, из Винодельни или из Сорта (Если мы предположим, что сорт является еще одним узлом строгого иерархического дерева, это только пример)

Одним из способов может быть включение свойства пути, как вы упомянули:

  • / origin / {id} / winery / {id} / разнообразие / {id}

Чтобы я мог получить список вин из сорта, применив запрос, подобный этому:

wines_query = Wine.all()
wines_query.filter('key_name >','/origin/toscana/winery/latoscana/variety/merlot/')
wines_query.filter('key_name <','/origin/toscana/winery/latoscana/variety/merlot/zzzzzzzz')

Или как это из Происхождения:

wines_query = Wine.all()
wines_query.filter('key_name >','/origin/toscana/')
wines_query.filter('key_name <','/origin/toscana/zzzzzz')

Спасибо!

1 Ответ

1 голос
/ 01 сентября 2010

Я не уверен, какие типы запросов вам нужно делать в дополнение к тем, которые упомянуты в этом вопросе, но хранение данных в явной иерархии предков сделало бы те, о которых вы спрашивали, довольно легко.

Например, чтобы получить все вина из определенного происхождения:

origin_key = db.Key.from_path('Origin', 123)
wines_query = db.Query(Wine).ancestor(origin_key)

или чтобы получить все вина из конкретного винзавода:

origin_key = db.Key.from_path('Origin', 123)
winery_key = db.Key.from_path('Winery', 456, parent=origin_key)
wines_query = db.Query(Wine).ancestor(winery_key)

и, при условии, что выСохраняя сорт как свойство модели Wine, все вина определенного сорта так же просты, как

wines_query = Wine.all().filter('variety =', 'merlot')

Одним из возможных недостатков этого строгого иерархического подхода является вид схемы URL, которую он может навязать вам.С иерархией, которая выглядит как

Origin -> Winery -> Wine

, вы должны знать имя ключа или идентификатор происхождения вина и винзавод, чтобы создать ключ для получения этого вина.Если вы уже не получили строковое представление ключа вина.Это в основном заставляет вас иметь URL для вина в одной из следующих форм:

  • /origin/{id}/winery/{id}/wine/{id}
  • /wine/{opaque and unfriendly datastore key as a string}

(Первый URLможно, конечно, заменить параметрами строки запроса; важная часть заключается в том, что для идентификации данного вина вам потребуются три различных элемента информации.)

Возможно, существуют другие альтернативы этим схемам URL, которые мне не приходили в голову,хотя.

...