【问题标题】:Popularity Algorithm人气算法
【发布时间】:2009-06-22 04:20:48
【问题描述】:

我正在制作一个类似于 digg 的网站,该网站将有一个包含不同类别的主页。我想显示最受欢迎的提交。

我们的评分系统只是“喜欢”,比如“我喜欢这个”等等。我们基本上希望显示每次“喜欢”次数最多的提交。我们希望有三个类别:历史流行度、上周和最后一天。

有人知道有什么方法可以帮忙吗?我不知道如何去做这件事并提高效率。我认为我们可以使用某种 cron-job 每 10 分钟运行一次,并在最后 10 分钟内获取点赞数……但有人告诉我这样做效率很低?

帮助?

谢谢!

【问题讨论】:

    标签: php sql algorithm popularity


    【解决方案1】:

    通常 Digg 和类似 Reddit 的网站会按提交日期而不是投票时间。这样,只需要一个简单的 SQL 查询就可以找到 X 时间段内最热门的提交。这是一个伪查询,使用此方法查找过去 24 小时内最受欢迎的 10 个链接:

    select * from submissions
     where (current_time - post_time) < 86400
     order by score desc limit 10
    

    基本上,此查询表示查找从现在到发布时间之间的秒数小于 86400(UNIX 时间为 24 小时)的所有提交。

    如果您真的想在 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;
    

    从这里开始,您只需一跳、跳过和内连接,就可以将帖子数据绑定到返回的 id。

    【讨论】:

    • 我写的基本一样,你比我快。 =)
    • 很好的答案...看起来虽然您描述的第一种方法更简单,但它无法处理一段时间前发布的内容突然重新流行的情况(可能是由于最近的新闻事件或什么)?第二种方法看起来更健壮,谢谢,我试试看!
    【解决方案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) 而不是 COUNTs。

    【讨论】:

      【解决方案3】:

      对于像 alltime 这样的稳定​​列表,上周,因为它们不应该改变得很快,所以我认为你应该将列表保存在缓存中,到期时间约为 1 天或更长时间。

      如果您关心实时正确计数,您可以通过比较缓存中最低页面的页面来检查每个页面视图。

      您需要做的就是注意缓存和实际数据库之间的同步。

      唐恩

      【讨论】:

      • 我的方法的目标是尽可能减少数据库查询,因为您不需要一直从数据库中获取顶部
      【解决方案4】:

      订单是当前时间的某个函数的查询可能会成为真正的性能问题。如果您可以按日历时间分组并在人们投票时更新每个分组的分数,事情就会变得简单得多。

      【讨论】:

      • ...嗯... ..什么?
      【解决方案5】:

      要完成nobody_的回答,我建议您阅读documentation(当然,如果您使用的是MySQL)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-20
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 1970-01-01
        • 2012-12-30
        相关资源
        最近更新 更多