NestedSet: подсчет кол-ва документов в категориях

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Ответить
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

есть категории nested-set-behavior

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

идеи такие
1. использовать геттеры и ДАО
alexZT
Сообщения: 362
Зарегистрирован: 2012.03.06, 11:33
Откуда: Украина/Житомир
Контактная информация:

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение alexZT »

дабы не мучить базу использовал для этого js и подсчитывал чайлдов (подходит для отображения кол-ва, но если данные нужны для использования в сценарии далее - нужно думать дальше)
я человек и мне свойственно ошибаться
yii@conference.jabber.ru
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

для того чтоб базу не мучать и задумался про дао
alexZT
Сообщения: 362
Зарегистрирован: 2012.03.06, 11:33
Откуда: Украина/Житомир
Контактная информация:

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение alexZT »

maxyc писал(а):для того чтоб базу не мучать и задумался про дао
не совсем понял как DAO прям сильно улучшит. Я одним запросом вынимаю дерево, а дальше js по нему бежит и просчитывает сколько на каком уровне элементов лежит и отображает кол-во (как писал - для отображения простого вполне подходит). Если я правильно понимаю задачу, то DAO не решит эту задачу одним-двумя запросами. Либо рекурсивно придется что-то опрашивать и от глубины дерева будет зависеть кол-во запросов. Либо придется вытаскивать дерево и потом его по алгоритму какому-то мусолить (например преобразовывать в многоуровневый массив и на каждом уровне подсчет проводить).
я человек и мне свойственно ошибаться
yii@conference.jabber.ru
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

alexZT писал(а):
maxyc писал(а):для того чтоб базу не мучать и задумался про дао
не совсем понял как DAO прям сильно улучшит.
отпишусь как руки дойдут
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

Это nested set
нам достаточно вытащить ID всех категорий, у которых left и right находится внутри left right текущей категории поиска. затем просто подставить в зарос COUNT
если реализовать геттером, то такой подход будет делать заведомо меньше запросов к бд относительно кол-ву категорий просмотра, потому что запрашиваться будет только по мере необходимости.
а можно все это реализовать одним запросом в ините или в том же гетере в статик кеше.
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

SELECT category_id, COUNT(*) FROM `forum_posts` where category_id in(select id from forum_categories where _left >=1 AND _right<=4 AND _root=2) GROUP BY category_id

примерный запрос при каждом вызове геттера
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

Код: Выделить всё

public function relations(){
        return array(
            'topics'=>array(self::HAS_MANY, 'YiiForumPost', 'category_id', 'condition'=>'topics.parent_id IS NULL'),
//            'countTopics'=>array(self::STAT, 'YiiForumPost', 'category_id', 'condition'=>'t.parent_id IS NULL'),
//            'countPosts'=>array(self::STAT, 'YiiForumPost', 'category_id', 'condition'=>'t.parent_id IS NOT NULL'),
        );
    }

    private function _getCount($root=true){
        $criteria = new CDbCriteria();
        $criteria->addCondition('parent_id IS '.($root ? '' : ' NOT ').' NULL');
        $criteria->addCondition('category_id IN (
                SELECT
                  id
                FROM
                  forum_categories
                WHERE
                  _left >= :left
                  AND _right<= :right
                  AND _root= :root)'
        );
        $criteria->params[':left']   =   $this->_left;
        $criteria->params[':right']  =   $this->_right;
        $criteria->params[':root']   =   $this->_root;

        return YiiForumPost::model()->count($criteria);
    }

    public function getCountTopics(){
        return $this->_getCount();
    }
    public function getCountPosts(){
        return $this->_getCount(true);
    }
короче. метод getCount принимает внутренний параметр какие данные искать. это не относится к делу.
далее, каждый вызов геттера делает запросы к бд. оно кешится самим мускулом, можно закешировать на уровне приложения.

тест запросов на ноуте. 400 постов. 100 топиков. 100 форомов. 10 категорий и подкатегорий
1 0.00052 0.00052 0.00052 0.00052
1 0.00038 0.00038 0.00038 0.00038
1 0.00038 0.00038 0.00038 0.00038
1 0.00033 0.00033 0.00033 0.00033
1 0.00023 0.00023 0.00023 0.00023
1 0.00017 0.00017 0.00017 0.00017
1 0.00014 0.00014 0.00014 0.00014
1 0.00011 0.00011 0.00011 0.00011
1 0.00009 0.00009 0.00009 0.00009
1 0.00008 0.00008 0.00008 0.00008
1 0.00008 0.00008 0.00008 0.00008
1 0.00008 0.00008 0.00008 0.00008
1 0.00007 0.00007 0.00007 0.00007
1 0.00007 0.00007 0.00007 0.00007
не вижу ничего плохого в таком подходе. даже если будет 100 форумов на страницу, нагрузки не вижу.
alexZT
Сообщения: 362
Зарегистрирован: 2012.03.06, 11:33
Откуда: Украина/Житомир
Контактная информация:

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение alexZT »

понял, в Вашем примере для Вас всё удачно складывается и работает (задача довольно простая - имея внутренний уровень подсчитать всё что вложено на один уровень вниз). Я решал другую задачу - многоуровневое вложение, потому если обсчитывать каждый уровень мне пришлось бы плодить кучу запросов.
я человек и мне свойственно ошибаться
yii@conference.jabber.ru
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

>подсчитать всё что вложено на один уровень вниз
где вы это увидели?

Код: Выделить всё

_left >= :left
AND _right<= :right
AND _root= :root
это прогоняется по всем уровням, включая текущий!

куча запросов нынче не так плохо. особенно при кешировании.
alexZT
Сообщения: 362
Зарегистрирован: 2012.03.06, 11:33
Откуда: Украина/Житомир
Контактная информация:

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение alexZT »

Куча запросов - это всегда куча запросов.
Я у Вас не вижу работы с параметром дерева - level, Вам он может и не нужен, а у меня задача в динамике для каждого левела считать чего и сколько внутри лежит, одним запросом каждый уровень я не знаю как можно посчитать каунтом, зато знаю как это пройти js'ом.
я человек и мне свойственно ошибаться
yii@conference.jabber.ru
maxyc
Сообщения: 124
Зарегистрирован: 2010.01.13, 09:11

Re: NestedSet: подсчет кол-ва документов в категориях

Сообщение maxyc »

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

вобщем по форумам пообщавшись понял, что самое лучшее решение это денормализация бд и при создании документов обновлять счетчик документов в таблице категорий
Ответить