To answer your questions:
(1) Yes, you can get a hash with the frequency of each :topic
like so:
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) This is "sustainable" in the sense that it does not grow in complexity as the number of posts/topics you introduce is increased (because you are still sampling from the top 200 posts, though getting the "top 200" will take slightly more compute time as the number of posts grows).
(3) I would think that impressions_count
would not be a very good way to keep track of what is trending, since to me impressions_count
has the total number of impressions, while you want some temporal aspect of it (e.g. impressions_this_week
).
So one way to do it would be to introduce an impressions_this_week
column that is updated at regular intervals. Then you can choose based on that.
Another way would be to write a method that uses the overall impressions_count
along with the created_at
or updated_at
timestamp to calculate how "hot" the post is. You could do this with a simple decay function and then tweak the constants of that function until you get the decay that you want. There is something similar to this concept shown here: http://blog.notdot.net/2009/12/Most-popular-metrics-in-App-Engine. Once you have that method written, you can just sort based on its output.