За последние 24 часа нас посетили 18211 программистов и 1682 робота. Сейчас ищут 1096 программистов ...

И снова деревья

Тема в разделе "Решения, алгоритмы", создана пользователем Amertox, 21 мар 2011.

  1. Amertox

    Amertox Активный пользователь

    С нами с:
    21 мар 2011
    Сообщения:
    17
    Симпатии:
    0
    Предположим, нужно создать структуру разделов с неограниченной вложенностью, а также страницы, каждая страница может быть прикреплена к одному разделу.

    Таблица страниц выглядет просто: поля id, name и id_cat. Тут все понятно.

    По поводу таблицы разделов, то тут обязательны поля: id, id_parent, name

    Все готово, структура готова, осталось только дописать редактор. Сложность заключается вот где: на странице сайте необходимо вывести список разделов 1-го уровня (т.е. у которых нет родителей), с количеством страниц (с учетом всех его подкаталогов), т.е. так "Раздел 1 - 10 страниц, Раздел 2 - 20 страниц". Я вижу следующие варианты:

    1) Сделать один запрос, выбрать все данные с двух таблиц, средствами PHP посчитать страницы.

    2) Сделать рекурсионные запросы в БД на каждый раздел, чтобы посчитать к-во в нем страниц.

    3) В таблицу cats добавить поля id_1, id_2 таким хитрым способом, чтобы, зная id текущего каталога можно было получить всех его потомков или предком (например, WHERE `id_1`< '$id'). Обновляться эти поля должны каждый раз при изменении любого раздела (добавление, изменение, удаление).

    4) При создании/удалении/изменении страницы считать к-во страниц и заносить в кеш.

    1) и 2) - слишком затраты 3) при каждом изменении разделов нужно пересоздавать поля id_1 и id_2, что не быстро + сам запрос на получение к-ва страниц будет все равно тяжелым. 4) Вроде хорошо, но если мы переносим страницу из одного раздела в другой, то необходимо обновлять кеш, а это уже муторно, потому что надо искать у каких именно разделов надо обновлять кеш.

    Пожалуйста, посоветуйте. Или скажите как это реализовано в других системах. Спасибо.
     
  2. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    если нужно только подсчитать количество записей только на одной странице (т.е. родительских разделов),
    то в таблицу страниц можно добавить поле id_root_cat, и уже по нему считать. как вариант
     
  3. Amertox

    Amertox Активный пользователь

    С нами с:
    21 мар 2011
    Сообщения:
    17
    Симпатии:
    0
    Вы наверное, меня не поняли.

    Есть разделы
    1.
    1.1.
    1.2.
    2.
    2.1
    2.2
    3.
    3.1

    и так далее с неограниченной вложенностью. У каждого раздела есть какое-то число страниц.

    Например, выводится на странице сайта список родителй:
    1.
    2.
    3.

    У каждого из эти каталогов должно отображаться к-во страниц в нем + к-во страниц во всех его подкаталогах, т.е.
    1. К-во страниц: 90 (это к-во страниц в 1. + 1.1. + .1.2. + 1.2.1 + и.д.)
     
  4. Amertox

    Amertox Активный пользователь

    С нами с:
    21 мар 2011
    Сообщения:
    17
    Симпатии:
    0
    При этом список разделов на странице сайта может выводиться не родительских, а скажем, второй вложенности:
    1.1.
    1.2.
    1.3.

    У них должно быть аналогичное к-во страниц.
     
  5. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    Amertox
    я подсказал способ для ограниченного использования, только для главной страницы.

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

    однако такой вариант требует усилий для поддержания таблицы связей в порядке при перемещении категорий внутри друг друга.
     
  6. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Изменить способ хранения дерева на Redundant Adjacency List или Nested Sets. Тогда считать можно будет одним запросом.
    ну и традиционная ссылка:
    http://www.php.ru/forum/viewtopic.php?t=27758
     
  7. Amertox

    Amertox Активный пользователь

    С нами с:
    21 мар 2011
    Сообщения:
    17
    Симпатии:
    0
    Спасибо. А можете вкратце объяснить, какая там структура, которая позволяет получить количество страниц одним запросом?
     
  8. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    В кратце, есть таблица с информацией и есть таблица с деревом.
    В таблице с информацией хранятся узлы дерева(id, name)
    В таблице с деревом хранятся связи между каждым узлом дерева и узлами, находящимся на пути от него к вершине, включая и саму вершину дерева, а так же расстояние от узла до предка (id_cat, id_par, level).
    В примере есть еще таблица со страницами(id, name, id_cat)
    Соответственно если надо получить сумму всех страниц которые относятся к категории и всем ее подкатегориям получаем:
    [sql]select count(pages.id) from pages join tree on pages.id_cat=tree.id_cat where id_par=@ourCatId[/sql]
     
  9. Amertox

    Amertox Активный пользователь

    С нами с:
    21 мар 2011
    Сообщения:
    17
    Симпатии:
    0
    Спасибо за объяснения. И еще вопрос:

    Как думаете, какая производительность у Вашего класса?

    Разделов будет примерно 10 000, количество вложение 1-5.

    К-во страниц - 200 000 - 500 000

    Обычный хостинг, думаю, такое не потянет?
     
  10. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    понятия не имею - не проверял.
     
  11. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Amertox
    Обычный хостинг
    понятие растяжимое.