Сортировка по произвольному полю и выборка всего дерева из БД - PullRequest
0 голосов
/ 03 мая 2010

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

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

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

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

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

1 Ответ

0 голосов
/ 03 мая 2010

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

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

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

...