Алгоритм популярности
Я делаю сайт, похожий на digg, который будет иметь домашнюю страницу с разными категориями. Я хочу отображать самые популярные материалы.
Наша рейтинговая система просто "нравится", например "Мне это нравится" и еще много чего. Мы в основном хотим отображать представления с наибольшим количеством "симпатий" за раз. Мы хотим иметь три категории: популярность во все времена, на прошлой неделе и в последний день.
Кто-нибудь знает способ помочь? Я понятия не имею, как это сделать и сделать его эффективным. Я думал, что мы могли бы использовать какую-то работу cron, чтобы работать каждые 10 минут и тянуть количество понравившихся за последние 10 минут... но мне сказали, что это довольно неэффективно?
Справка
Спасибо!
Ответы
Ответ 1
Обычно сайты, относящиеся к Digg и Reddit, относятся к дате представления, а не по времени голосования. Таким образом, все, что требуется, это простой SQL-запрос, чтобы найти верхние представления за X-период. Здесь псевдо-запрос для поиска 10 самых популярных ссылок за последние 24 часа с использованием этого метода:
select * from submissions
where (current_time - post_time) < 86400
order by score desc limit 10
В основном, этот запрос говорит, чтобы найти все материалы, в которых количество секунд между временем и временем его размещения было меньше 86400, что составляет 24 часа в UNIX.
Если вы действительно хотите измерить популярность в течение X-интервала времени, вам нужно сохранить пост и время для каждого голосования в другой таблице:
create table votes (
post foreign key references submissions(id),
time datetime,
vote integer); -- +1 for upvote, -1 for downvote
Затем вы можете создать список наиболее популярных сообщений между X и Y раз так:
select sum(vote), post from votes
where X < time and time < Y
group by post
order by sum(vote) desc limit 10;
Отсюда вы просто прыгаете, пропустите и внутреннее соединение от получения данных, связанных с возвращенными идентификаторами.
Ответ 2
Есть ли у вас достойная настройка БД? Можем ли мы узнать о ваших деталях и показателях CREATE TABLE
? Предполагая разумную настройку, БД должна быть в состоянии вытащить счета, которые вам потребуются достаточно быстро, чтобы удовлетворить ваши потребности! Например (без индексов и ключей, которые несколько зависят от того, какой механизм БД вы используете), учитывая две таблицы:
CREATE TABLE submissions (subid INT, when DATETIME, etc etc)
CREATE TABLE likes (subid INT, when DATETIME, etc etc)
вы можете получить лучшие 33 популярных всплывающих сообщения как
SELECT *, COUNT(likes.subid) AS score
FROM submissions
JOIN likes USING(subid)
GROUP BY submissions.subid
ORDER BY COUNT(likes.subid) DESC
LIMIT 33
и те, которые проголосовали в течение определенного промежутка времени, как
SELECT *, COUNT(likes.subid) AS score
FROM submissions
JOIN likes USING(subid)
WHERE likes.when BETWEEN initial_time AND final_time
GROUP BY submissions.subid
ORDER BY COUNT(likes.subid) DESC
LIMIT 33
Если вы сохраняли "голоса" (положительные или отрицательные) в likes
вместо того, чтобы просто считать каждую запись там как +1
, вы могли бы просто использовать SUM(likes.vote)
вместо COUNT
s.
Ответ 3
Для стабильного списка, такого как alltime, lastweek, потому что они не должны меняться очень быстро, поэтому я думаю, что вы должны сохранить список в кеше с истечением срока действия около 1 дня или дольше.
Если вы относитесь к правильному счету в реальном времени, вы можете проверить его на каждом просмотре страницы, сравнив страницу с самой низкой страницей в кеше.
Все, что вам нужно сделать, - это синхронизация между кешем и фактической базой данных.
thethanghn
Ответ 4
Запросы, в которых порядок является некоторой функцией текущего времени, могут стать настоящими проблемами производительности. Все становится намного проще, если вы можете ведро по календарному времени и обновлять баллы для каждого ведра, когда люди голосуют.
Ответ 5
Чтобы заполнить nobody_ answer, я предлагаю вам прочитать документацию (если вы, конечно, используете MySQL).