Dubrowsky
Хроники одного дупла
Блогово  →  WebDev  → 

Прикрутил "крутые посты"

11 Марта 2012 года

На бложике моем в правой колонке появился блок "крутые посты". Ща расскажу, как он работает.

1. Чего хотелось добиться?

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

2. А чо это за посты?

Интересные в моем представлении - посты, которые:

  • собрали дофига камментов
  • и/или написаны не очень давно
  • если юзер смотрит какой-то раздел - посты из этого же раздела интереснее

3. И как это работает?

Ну, я писал уже, что у меня тут не какой-нибудь Вордпресс, а своя вело-цмска. Чувак с вордпрессом включил бы какой-нибудь плагин - и лишился бы при этом удовольствия чо-то придумать и сделать своими руками. А вот не лишился :) Рассказываю любопытным про реализацию:

  1. Поскольку у меня тут не шибко дофига текстов, мы можем считать рейтинг "на лету" (тем более что есть "контексто-зависимый фактор" в виде текущего раздела
  2. То есть наша задача - добавить к SQL-запросу, показывающему посты, вычисляемое поле "rating" и отсортировать по нему результаты
  3. В тупом виде формула такая: "(кол-во комментов / возраст поста) * соответствие разделу"
  4. Но ее надо настроить, расставив коэффициенты, чтоб было красиво.
  5. Возраст я решил считать, беря квадратный корень от кол-ва секунд, прошедших с момента написания поста:


    SQRT(UNIX_TIMESTAMP(NOW()) - T.creation_date)
  6. Если на это делить кол-во комментов "как есть", вверх полезут старые посты с большим кол-вом комментов. Поигравшись с результатами, возвел кол-во комментов в степень 0.5:
    POW(T.count_comments,0.5)
  7. Добавляем фактор раздела, если он есть. Мне понравилось умножение на 2.5:
    IF(S.parent = %section_id, 2.5, 1)
  8. Итоговый запрос получается какой-то такой:
    SELECT T.*,
       POW(T.count_comments,0.5) * 
       SQRT(UNIX_TIMESTAMP(NOW()) - T.creation_date) *
       IF(S.parent = %section_id, 2.5, 1) as rating
    FROM posts T
    ORDER BY rating DESC
    LIMIT 20
  9. Остается добавить выбор 5 случайных постов из полученных 20 с наибольшим рейтингом. Любой пыхарь, используя shuffle() и array_slice(), сделает это за полторы минуты :)
  10. Для понта полученное значение рейтинга можно вывести на экран. Оно нифига не значит, но внушает. Чтоб оно было читаемее, сделаем round($rating*10000, 2)
  11. Для красоты еще раз сортируем отобранные 5 случайных записей по рейтингу. Я это сделал прямо в XSL-шаблоне.
  12. Остается прикрутить стили :)

Это алгоритм в общем виде, если кто захочет реализовать у себя - обращайтесь, чо, подскажу :)

4. Можно ли улучшить?

Ага, наверняка.

Во-первых, можно считать кол-во просмотров и использовать в формуле (желательно - нормализовав на возраст поста).

Во-вторых, аналогично разделу можно использовать теги, типа что при просмотре поста про синхронный перевод в Киеве например, справа появлялось чо-то еще про Киев. Но это усложняет и утяжеляет запрос (т.к. теги хранятся мэни-ту-мэни), к тому же уже реализовано в блоке "что еще почитать" в конце поста :)

В-третьих, конечно, по уму этот рейтинг надо хранить и пересчитывать типа раз в сутки.

Камменты

Николай Дубровскийон самый11.03.2012, 16:57#
А чо, может у кого есть идеи, как его еще улучшить? ))
Николай Дубровскийон самый11.03.2012, 17:01#
Вот, спросил - и сам сразу придумал улучшение :)

Когда пост только появился, в знаменателе получается маленькое значение (а может и ноль появиться, если например есть отложенная публикация и кто-то зашел секунда-в-секунду). Вот, после того, как я добавил сюда комментарий, у этого поста рейтинг стал типа 2К.

Чтоб от такого эффекта избавиться, я добавил лишние сутки возраста всем постам:

<!-- CODE -->
SQRT(UNIX_TIMESTAMP(NOW()) - T.creation_date + 60*60*24)


Стало лучше :)
Давид11.03.2012, 17:25#
а формула Бейеса не катит ;)?
Николай Дубровскийон самый11.03.2012, 17:28#
Давид, может и катит )) А как ее тут применить, поясни? У меня с матаном траблы, я ж гуманитарий ваще =)
Давид11.03.2012, 17:48#
у самих кстати с рядом проектов были траблы с рейтингом, пока что круче Байеса ничего не придумали. ИМХО.
покурили теовер, покурили хабр и матфорум.
http://habrahabr.ru/qa/3491/
http://habrahabr.ru/blogs/webdev/53606/
http://www.mathforum.ru/forum/read/1/687/688/
Николай Дубровскийон самый11.03.2012, 18:02#
Спасибо за ссылки, идею понял )
С такой задачей сталкивался в мыслях, до практики кажется не дошло. Но задача актуальная, согласен.
Подумаю на досуге, ок )
DrJeans11.03.2012, 18:10#
Прочитал по диагонали и решил, что Давид предлагает формулы на Бейсике! Сижу втыкаю, шозанах? Порвало! :D
Давид11.03.2012, 18:17#
DrJeans, блииин, эт когда я писал на бейсике.. дай Бог памяти, первый раз класс 5-6 наверное, и уже на вижуале где-то лет в 20..
ужоснах..

Написать коммент: памятка постеру

 

Крутые посты wtf??? →

02.10.2012 · 90 камментов · рейтинг 19.23
15.02.2013 · 23 каммента · рейтинг 10.12
14.07.2017 · 1 каммент · рейтинг 9.15
30.01.2013 · 13 камментов · рейтинг 7.57
28.03.2008 · 23 каммента · рейтинг 6.99

Последне камменты

22.07.2017  СергейПочему не работает form.submit(): Также столкнулся с неработающим .submit() при отпр...
20.07.2017  СергейСвязь: Здравствуйте. Хочу предложить Вам тройной обмен п...
17.07.2017  Илья АрхипкинСколько журналистов в России?: Мне рассказывали как журналисты освещали акцию в К...
21.05.2017  Vadim GukОбработка кликов и цели в Яндекс.Метрике, улучшенный вариант: Большое спасибо за решение задачи.
20.05.2017  ДмитрийТестовое задание для PHP-программиста (Junior): А джуны ещё нужны у вас в компании?

Статсы