Проблемы с фильтрацией ресурсов (больше 2000шт.)
        Стоит задача отфильтровать ресурсы: вывести те ресурсы, у которых больше 20 просмотров (HitsPage), комментов больше 0 (Tickets), и которые опубликованы больше месяца назад.
Написал сниппет, но при обработке большого количества ресурсов страница с вызовом сниппета не загружается. Как оптимизировать код?
    
    
                                                        Написал сниппет, но при обработке большого количества ресурсов страница с вызовом сниппета не загружается. Как оптимизировать код?
$mounth = 2629743;
$date = strtotime('now')-$mounth;
$where = array(
	'parent' => 19,
	'publishedon:<' => $date
);
$resources = $modx->getCollection('modResource', $where);
foreach ($resources as $k => $res) {
    //получаем id
    $id = $res->get('id');
    //получаем количество комментов
    $q = $modx->newQuery('modResource', $id);
    $q->leftJoin('TicketThread','TicketThread', "`TicketThread`.`name` = 'resource-{$id}'");
    $q->leftJoin('TicketComment','TicketComment', "`TicketThread`.`id` = `TicketComment`.`thread`");
    $q->select('COUNT(`TicketComment`.`id`) as `comments`');
    
    $count = 0;
    if ($q->prepare() && $q->stmt->execute()) {
    	$count = (integer) $q->stmt->fetch(PDO::FETCH_COLUMN);
    }
    //получаем дату, количество просмотров и заголовок
    $date = $res->get('publishedon');
    $hits = $res->getTVValue(3);
    $titles = $res->get('pagetitle');
    
    //если опубликован больше месяца назад, просмотров больше 20 и комментов больше 0, то выводим
    if ($hits >= 20 and $count > 0) {
        $output .= $date. " | П: ". $hits. " | К: ". $count. "</br>". $titles.  "<hr>";
    }
}
return $output;    
            
                Поблагодарить автора            
            
                 Отправить деньги            
        
        
            Комментарии: 6
                Убрать getCollection, использовать getIterator
modxclub.ru/topics/xpdogetiterator-vmesto-xpdogetcollection.html
В критерию можно добавить выбор только нужных колонок (publishedon, pagetitle, id)
Можно сразу присоединить и таблицу с TV hits по contentid и tmplvarid = 3
                    modxclub.ru/topics/xpdogetiterator-vmesto-xpdogetcollection.html
В критерию можно добавить выбор только нужных колонок (publishedon, pagetitle, id)
Можно сразу присоединить и таблицу с TV hits по contentid и tmplvarid = 3
                Я не уверен, конечно, но лучше использовать newQuery. С getIterator почти нет опыта, но читал, что меньше всего нагрузка именно при newQuery.            
                    
                Вы путаете, newQuery — это создание запроса xPDOQuery, а getCollection и getIterator получение результата на основании параметров (это может быть и обычный массив и xPDOQuery)
В случае getCollection и getIterator вы получаете объекты xpdo, из которых вы можете получить подготовленные данные через метод get.
                    В случае getCollection и getIterator вы получаете объекты xpdo, из которых вы можете получить подготовленные данные через метод get.
if ($q->prepare() && $q->stmt->execute()) {
    	$count = (integer) $q->stmt->fetch(PDO::FETCH_COLUMN);
    }А в данном случае вы получаете результат из базы данных            Вы путаете, newQuery — это создание запроса xPDOQuery, а getCollection и getIterator получение результата на основании параметров (это может быть и обычный массив и xPDOQuery)Как я понял — объекты не нужно получать, ведь там просто вывод результатов.
В случае getCollection и getIterator вы получаете объекты xpdo, из которых вы можете получить подготовленные данные через метод get.
Я вчитался в код и офигел… Сначала выбираются минимум 2000 страниц, после чего для каждой из них идет запрос к базе.
Да, тут вообще вопрос в другом — как избавится от такого количества запросов.
                Автор, окстись!
Очень плохой код.
Как это сейчас работает: сначала через getCollection забираются 2000+ ресурсов, которые опубликованы. Далее мы получаем их id и для каждого делаем запрос к бд!
Это очень плохая идея.
Как минимум те же id можно получить через newQuery — так будет быстрее.
А во вторых желательно сделать 1 запрос к бд, а не 2001.
Почитай мануалы.
А вообще я бы примерно так сделал (вообще не гарантирую, что будет работать, пишу на глазок).
            
                    Очень плохой код.
Как это сейчас работает: сначала через getCollection забираются 2000+ ресурсов, которые опубликованы. Далее мы получаем их id и для каждого делаем запрос к бд!
Это очень плохая идея.
Как минимум те же id можно получить через newQuery — так будет быстрее.
А во вторых желательно сделать 1 запрос к бд, а не 2001.
Почитай мануалы.
А вообще я бы примерно так сделал (вообще не гарантирую, что будет работать, пишу на глазок).
$mounth = 2629743;
$date = strtotime('now')-$mounth;
$where = array(
	'parent' => 19,
	'publishedon:<' => $date,
	'comments:>' => 20
	//тут надо добавить что-то про hits, но для этого сделать join таблицы modTemplateVar
);
$q = $modx->newQuery('modResource', $id);
$q->leftJoin('TicketThread','TicketThread', "`TicketThread`.`name` = 'resource-{$id}'");
$q->leftJoin('TicketComment','TicketComment', "`TicketThread`.`id` = `TicketComment`.`thread`");
$q->select('COUNT(`TicketComment`.`id`) as `comments`');
$q->where($where);
if ($q->prepare() && $q->stmt->execute()) {
    	$data = $q->stmt->fetch(PDO::FETCH_COLUMN);
	foreach ($data as $res) {
		//тут код вывода
	}
}Вариант такого типа будет работать в сотни раз быстрее
                Переделал. Не уверен, что все правильно сделал, но работает в разы быстрее. 
Условия выборки немного изменились: вывести статьи, у которых просмотров меньше 20, количество комментов = 0, и, которые опубликованы больше трех недель назад.
                    Условия выборки немного изменились: вывести статьи, у которых просмотров меньше 20, количество комментов = 0, и, которые опубликованы больше трех недель назад.
$week = 604800;
$cond_date = strtotime('now')-$week*3;
$q_test = " SELECT 
                modx_site_content.id, 
                modx_site_content.properties, 
                modx_site_content.publishedon,
                modx_tickets_threads.comments 
            FROM 
                `modx_site_content`, 
                `modx_tickets_threads` 
            WHERE 
                modx_site_content.id = modx_tickets_threads.resource 
                AND 
                modx_site_content.parent = '19'";
$result = $modx->query($q_test);
$rows = $result->fetch();
do {
    $id = $rows['id'];
    $comments = $rows['comments'];
    $date = $rows['publishedon'];
    $visits = preg_replace("/[^0-9]/", '', $rows['properties']);
    
    if ($comments == 0 and $visits <= 20 and $date < $cond_date) {
        echo "<pre>";
        echo "id = ". $id. "<br />";
        echo "comments = ". $comments. "<br />";
        echo "pubdate = ". date("Y-m-d",$date). "<br />";
        echo "visits = ". $visits;
        echo "</pre>";
    }
}
while ($rows = $result->fetch());            
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.