Ответ 1
Существует несколько известных способов представления деревьев в базах данных; у каждого из них есть свои плюсы и минусы. Вот наиболее распространенные:
- Список аджакции, где каждый node хранит идентификатор своего родителя.
- Материализованный путь, который описывает стратегию Keyur. Это также подход, используемый группами объектов (например, родительскими объектами) в App Engine. Это также более или менее то, что вы описываете в своем обновлении.
- Вложенные наборы, где каждый node имеет идентификаторы "left" и "right", так что все дочерние узлы содержатся в этом диапазоне.
- Списки аджакции, связанные с идентификатором корня.
Каждый из них имеет свои преимущества и недостатки. Списки адъюенции просты и дешевы для обновления, но требуют нескольких запросов для извлечения поддерева (по одному для каждого родителя node). Расширенные списки смежности позволяют извлекать целое дерево, сохраняя идентификатор корня node в каждой записи.
Материализованные пути легко внедряются и дешевы для обновления и позволяют запрашивать произвольные поддеревья, но накладывают дополнительные накладные расходы на глубокие деревья.
Вложенные наборы сложнее реализовать и требуют обновления, в среднем, половины узлов при каждом вставке. Они позволяют вам запрашивать произвольные поддеревья, без увеличения длины материализованного пути длины.
В вашем конкретном случае, похоже, вам вообще не нужна древовидная структура: каждая история, разветвленная с оригинала, хотя может быть, стоит одна. Я бы предположил, что у вас есть модель "История", которая содержит список ключей его абзацев (например, в Python a db.ListProperty(db.Key)). Чтобы сделать историю, вы получите Историю, затем сделайте пакетную выборку для всех абзацев. Чтобы развернуть историю, просто продублируйте запись истории - оставив ссылки на абзацы неизменными.