Django:如何创建排行榜

Pau*_*jan 8 python sql django leaderboard

假设我有大约1,000,000个用户.我想找出任何给定用户所处的位置,以及他周围的用户.用户可以随时获得新的成就,如果他能看到他的常规更新,那将是非常棒的.

老实说,我认为这样做的每一种方式在时间和/或记忆方面都会非常昂贵.想法?到目前为止,我最接近的想法是让用户离线并构建百分位桶,但这无法向用户显示他的确切位置.

一些代码,如果这可以帮助你django人:

class Alias(models.Model) :
    awards = models.ManyToManyField('Award', through='Achiever')

    @property
    def points(self) :
        p = cache.get('alias_points_' + str(self.id))
        if p is not None : return p

        points = 0
        for a in self.achiever_set.all() :
            points += a.award.points * a.count

        cache.set('alias_points_' + str(self.id), points, 60 * 60) # 1 hour
        return points

class Award(MyBaseModel):
    owner_points = models.IntegerField(help_text="A non-normalized point value. Very subjective but try to be consistent. Should be proporional. 2x points = 2x effort (or skill)")
    true_points = models.FloatField(help_text="The true value of this award. Recalculated with a cron job. Based on number of people who won it", editable=False, null=True)

    @property
    def points(self) :
        if self.true_points :
            # blend true_points into real points over 30 days
            age = datetime.now() - self.created
            blend_days = 30
            if age > timedelta(days=blend_days) :
                age = timedelta(days=blend_days)
            num_days = 1.0 * age.days / blend_days
            r = self.true_points * num_days + self.owner_points * (1 - num_days)
            return int(r * 10) / 10.0

        else :
            return self.owner_points


class Achiever(MyBaseModel):
    award = models.ForeignKey(Award)
    alias = models.ForeignKey(Alias)
    count = models.IntegerField(default=1)
Run Code Online (Sandbox Code Playgroud)

Dus*_*etz 4

我认为《Counterstrike》通过要求用户达到排名的最低门槛来解决这个问题——你只需要准确地排序前 10% 或其他什么。

如果您想对每个人进行排序,请考虑您不需要对它们进行完美排序:将它们排序为 2 位有效数字。对于 100 万用户,您可以实时更新前 100 个用户的排行榜,接下来的 1000 个用户精确到 10 个,然后大众精确到 1% 或 10%。你不会在一轮中从第 500,000 位跳到第 99 位。

获得 500,000 位以上和以下的 10 个用户上下文是没有意义的——由于指数分布,大众的排序在每一轮中都会非常不稳定。

编辑:看看SO 排行榜。现在转到2500 页中的第 500 页(大约第 20 个百分点)。告诉代表“157”的人,他们两边的 10 个人也有代表“157”,这有什么意义吗?如果您的代表次数上升或下降一个点,您就会上升 20 位。更极端的是,目前排名靠后的 1056 个页面(共 2538 个页面),或者说排名靠后的 42% 的用户,与代表 1 并列。您再获得一分,并且您跳转了 1055 个页面。这大约增加了 37,000 名等级。告诉他们“如果你再得到一分,你就可以击败 37,000 人!”可能会很酷。但是 37k 数字有多少位有效数字有关系吗?

在你已经达到顶峰之前,了解阶梯上的同行是没有任何价值的,因为除了顶峰以外的任何地方,他们的数量都是压倒性的。