[Tickets] Подсчет популярности

Вчера Евгений Борисов предложил способ подсчета популярности заметок на сайте.

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

Результатом стала возможность вывода на главной всех заметок (кроме работы и вопросов) по рейтингу.

Для этого я написал простой сниппет, который отдаёт отсортированные id тикетов в getTickets, а тот их выводит.
Вот он — сниппет TicketRating:
<?php
$exclude = array(32,36); // Родители, которых нужно исключить из выборки
$rating = array();

$q = $modx->newQuery('Ticket', array('class_key' => 'Ticket', 'published' => 1, 'deleted' => 0));
$q->leftJoin('TicketThread', 'TicketThread', 'TicketThread.resource = Ticket.id');
$q->where(array('parent:NOT IN' => $exclude));
$q->select('Ticket.id,Ticket.createdon,TicketThread.id as thread');
$q->sortby('createdon', 'desc');
if ($q->prepare() && $q->stmt->execute()) {
	while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
		$comments = $views = 0;
		
		$sql = "SELECT COUNT(id) FROM {$modx->getTableName('TicketComment')} WHERE `thread` = {$row['thread']} AND `published` = 1";
		$stmt = $modx->prepare($sql);
		$stmt->execute();
		$comments = $stmt->fetch(PDO::FETCH_COLUMN);

		$sql = "SELECT COUNT(parent) FROM {$modx->getTableName('TicketView')} WHERE `parent` = {$row['id']}";
		$stmt = $modx->prepare($sql);
		$stmt->execute();
		$views = $stmt->fetch(PDO::FETCH_COLUMN);
		
		$days = round((time() - $row['createdon']) / 86400);
		
		// Алгоритм взят отсюда http://blog.agel-nash.ru/2013/7/rating.html
		$ageK= (1-$days/($days+1)); //Возрастной коэффициент
		$rang = $ageK + $ageK*$views + $ageK*$comments + $comments; //Рейтинг
		
		$rating[$row['id']] = $rang;
	}
}

arsort($rating);
return implode(',', array_keys($rating));

Сниппет работает довольно шустро, обсчитывая 250 тикетов за 0,2 — 0,3 секунды, а 1300 тикетов за 0,8 сек. Конечно, к нему можно прикрутить кэширование и хранение результатов в БД, если нужно побыстрее.

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

Использовать сниппет очень просто:
[[!getTickets?
	&parents=`0`
	&sortby=``
	&resources=`[[!TicketRating]]`
]]
Обязательно нужно обновить Tickets до версии 1.0.0 pl1 из нашего репозитория. Только она умеет выводить документы в том порядке, в каком они указаны в &resources. Конечно, заодно нужно обновить и pdoTools.

На всякий случай, еще раз ссылочка на вывод по рейтингу.

Следующая заметка
[Tickets] Версия 1.1.0 beta - Управление подписками
Предыдущая заметка
[pdoTools] pdoResources 1.4.1


Комментарии ()

  1. Александр Донский 22 июля 2013, 23:31 # 0
    Спасибо ребята, эта возможность меня давно волновала! P.S. Еще бы свою кнопку «Like» ;)
    1. Василий Наумкин 23 июля 2013, 05:56 # +1
      Изначально в планах такое было, а теперь даже и не знаю.

      Уже год без этой кнопки живем — нет ни срачей, ни холиваров, ни обидок за минусы. Есть мнение, что старая добрая модерация гораздо лучше работает, чем «саморегулируемое сообщество», основанное на «демократическом голосовании».

      В общем, не уверен, что like будет в Tickets.
    2. Евгений 03 декабря 2014, 09:29 # 0
      Василий, а реально ли переделать подсчет просмотров тикета с учетом просмотров даже неавторизованных посетителей?

      Простите за некропост.
      1. Илья Уткин 03 декабря 2014, 16:07 # +1
        Я у себя на сайте так сделал. Вот статья соответствующая: Изменяем алгоритм подсчета просмотров в Tickets
      Добавление новых комментариев отключено.