I've built something similiar to this in the past with Redis. Each time a 'tag' is hit, it gets one point. Every hour, the value of all scores, for everything hit ever is dropped by 10%. Then you order by points.
So a tag that gets hit 10 times in the first hour, will have 10 points. After an hour, those points are degraded 10%, leaving 9 points. An hour later, it's 8.1 points, then 7.2 points and so on. Of course, more views adds more points.
Since all scores are degraded 10% every hour, the value of previous hits received drops over time, and anything that is being hit regularly, or even going viral, will have more undegraded points.
In Drupal terms for example, consider a tag that is a taxonomy term attached to a comment. When new comments are saved, you can loop through any attached terms in hook_comment_insert() to add a point for each tag:
function HOOK_comment_insert(\Drupal\Core\Entity\EntityInterface $comment) {
foreach ($comment->get('field_tag')->value as $tag) {
some_php_function_that_adds_a_point_for_a_tag_in_reds($tag);
}
}
Then, you would want to create a cron implementation that degrades the points stored in Redis:
function HOOK_cron() {
some_function_that_deletes_all_tag_scores_by_10_percent();
}
And you set the cron to run every hour. Although, in a real-world setting, I would actually integrate my module with the Ultimate Cron module for more granular control over cron runs, to better ensure that my process is run every hour.