Реализация трендовых тем
В настоящее время я нахожусь на пути реализации Trending Topics в моем приложении Rails.
Что у меня сейчас есть, так это:
Каждый пост имеет topic
атрибут от 2 до 3 слов, описывающий его тему.
Затем я получаю лучшие посты по количеству просмотров (у меня также есть лайки и избранное, но пока я использую просто просмотры):
def trending_topics
Post.order("COALESCE(impressions_count, 0) DESC").limit(200)
end
И тогда я просто выбираю только уникальные темы и показываю их несколько:
<% trending_topics.select(:topic).map(&:topic).uniq.take(10).each do |topic| %>
<li><%= topic %></li>
<% end %>
Мои вопросы:
- Есть ли способ получить наиболее часто появляющиеся
:topic
, ранжировать их, и выбрать сливки урожая тех? - Это устойчивый способ отслеживать популярные темы? Если нет, есть ли способ сделать его более эффективным?
- Есть ли лучший способ реализовать функцию, которая ищет наиболее популярные и частые
:topic
атрибуты в постах?
2 ответа
Чтобы ответить на ваши вопросы:
(1) Да, вы можете получить хэш с частотой каждого :topic
вот так:
array = trending_topics.select(:topic).map(&:topic)
freq = array.inject(Hash.new(0)) { |h,v| h[v] += 1; h }
# => {'topic1'=>3, 'topic2'=>3, 'topic3'=>1, ...}
(2) Это является "устойчивым" в том смысле, что его сложность не возрастает по мере увеличения количества вводимых вами постов / тем (поскольку вы по-прежнему отбираете 200 лучших постов, хотя получение "топ 200" займет немного больше времени вычислений по мере роста количества постов).
(3) Я думаю, что impressions_count
было бы не очень хорошим способом отслеживать то, что в тренде, так как для меня impressions_count
имеет общее количество показов, в то время как вы хотите некоторый временной аспект (например, impressions_this_week
).
Так что один из способов сделать это было бы ввести impressions_this_week
столбец, который обновляется через равные промежутки времени. Тогда вы можете выбрать на основе этого.
Другим способом было бы написать метод, который использует общий impressions_count
вместе с created_at
или же updated_at
отметка времени, чтобы вычислить, насколько "горячим" является пост. Вы можете сделать это с помощью простой функции затухания, а затем настраивать константы этой функции до тех пор, пока не получите нужный затухание. Здесь есть нечто похожее на эту концепцию: http://blog.notdot.net/2009/12/Most-popular-metrics-in-App-Engine. После того, как вы написали этот метод, вы можете просто отсортировать его по выводу.
Если вам нужно что-то более сложное, чем ваш текущий алгоритм ранжирования, вам, вероятно, стоит взглянуть на то, как такие сайты, как reddit и hackernew s, решают эту проблему. Это довольно сложно, но вы должны быть в состоянии найти реализацию каждого алгоритма в Ruby, если вы гуглите его.