Сортировка по пользовательскому полю и выборка всего дерева из БД

Я пытаюсь сделать файловый браузер в виде дерева, и у меня проблема как-то его отсортировать. Я использую для этого PHP и MySQL. Я создал смешанный (вложенный набор + смежность) элемент таблицы со следующими полями:

element_id, left_key, right_key, level, parent_id, element_name, element_type (enum: 'folder','file'), element_size.

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

Функция сканирования указанного каталога и заполнения таблицы работает корректно. Примечательно, что я добавляю элементы в дерево в определенном порядке: сначала папки, а затем файлы.

После этого я могу легко получить и отобразить всю таблицу на странице с помощью простого запроса:

SELECT * FROM element WHERE 1=1 ORDER BY left_key

С результатом этого запроса и другой функции я могу сгенерировать правильный HTML-код (<ul><li>... and so on). для отображения дерева.

Теперь вернемся к вопросу (наконец, да?). Я изо всех сил пытаюсь добавить функцию сортировки. Например, я хочу упорядочить результат по размеру. Здесь мне нужно помнить всю иерархию дерева и правил: сначала папки, потом файлы.

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

SELECT * FROM element WHERE parent_id = {$parentId} ORDER BY element_type (so folders would be first), size (or name for example) asc/desc

После этого для каждого результата с типом = 'folder' я отправлю еще один запрос, чтобы получить его содержимое.

Также можно получить целое дерево с помощью left_key и после этого отсортировать его в PHP как массив, но я думаю, что это было бы хуже :)

Интересно, есть ли лучший и более эффективный способ сделать это?


mysql php nested tree
person Niaxon    schedule 03.05.2010    source источник


Ответы (1)


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

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

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

person Hans    schedule 03.05.2010