Лучший способ отобразить дерево глубины для использования в PHP (MySQL / XML /?) - PullRequest
3 голосов
/ 04 декабря 2008

В настоящее время я переписываю приложение, с помощью которого учителя могут планировать учебный план онлайн.

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

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

Когда я изначально проектировал систему, я исходил из того, что все результаты учеников следовали схожей иерархии. То есть есть именованные вложенные контейнеры, а затем результаты.

Исходный набор результатов, который я ввел, был трехуровневым. Таким образом, моя база данных имеет следующую структуру:

=========================

Таблицы, выделенные жирным шрифтом

h1

id, Name

h2

id, parent___id (h1_id), Имя

h3

id, parent___id (h2_id), Имя

результат

id, parent___id (h3_id), Имя

=========================

Помимо очевидной невозможности добавить n / уровни иерархии, этот метод также затруднил отображение списка всех стандартов без рекурсивных запросов к базе данных.

После того, как результаты учеников (и их родительские категории) были добавлены, есть очень мало причин для их изменения каким-либо образом. Основное требование - их легко и эффективно читать.

До настоящего времени все результаты учащихся из разных школ / штатов / стран примерно соответствовали моему предположению. Это не всегда так.

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

Учитывая вышесказанное, каков наилучший для меня способ хранения всех различных наборов результатов учащихся? Некоторые из идей, которые у меня были, перечислены ниже.

  • Продолжайте использовать 4 таблицы в базе данных, выбирая либо использовать recusion, либо множество объединений

  • Использовать вложенные множества

  • XML (Глобальный XML-файл для всех наборов или XML-файл для каждого)

Ответы [ 3 ]

6 голосов
/ 04 декабря 2008

Я не знаю, что вам на самом деле нужно 4 таблицы для этого.

Если у вас есть одна таблица, которая отслеживает parent_id и уровень, вы можете иметь бесконечные уровни.

результат

id, parent_id, уровень, имя

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

Альтернативой являются вложенные множества. В этом случае вы все равно объединяетесь в одну таблицу, но используете заданные вещи для отслеживания уровней.

Какой из них использовать, зависит от вашего приложения.

интенсивное чтение: вложенные множества

интенсивная запись: родительское дерево штука

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

Когда вы просто отслеживаете parent_id, вы можете перемещать или удалять узлы по отдельности.

PS: я голосую против XML. У вас те же рекурсивные проблемы, плюс накладные расходы на синтаксический анализ данных, а также на их хранение в БД или в файловой системе (что приведет к проблемам параллелизма).

1 голос
/ 04 декабря 2008

Я согласен с другими постерами - я думаю, что вложенные наборы - это путь.

Смотрите здесь:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

Он объясняет теорию и сравнивает ее с тем, что вы уже используете - что на самом деле является поворотом смежности. Он показывает +/- их всех и должен помочь вам принять решение, основанное на всех тонкостях вашего проекта.

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

http://book.cakephp.org/view/91/Tree

0 голосов
/ 04 ноября 2009

есть еще один способ обработки деревьев в базе данных, который, возможно, не такой «умный», как вложенные множества и другие шаблоны, описанные здесь, но который действительно эффективен и прост:

вместо сохранения уровня (или глубины) элемента, вы можете сохранить полный путь в дереве, например:

A
  B
  C
    D
  E

будет храниться так:

item  |  parent  |  path
----------------------------
A     |  NULL    |  A
B     |  A       |  A--B
C     |  A       |  A--C
D     |  C       |  A--C--D
E     |  A       |  A--E

тогда вы можете легко получить:

  • (чистый SQL) все прямые потомки элемента с предложением where parent = ''
  • (чистый SQL) все прямые и непрямые дочерние элементы, где путь LIKE 'PARENT -%' предложение
  • (PHP) глубина узла (count (explode ('-', $ path)) *

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

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...