2009-09-08 134 views
8

可以说我有大约100万用户。我想知道给定用户在哪个位置以及哪些用户在他身边。用户可以随时获得新的成就,如果他能看到他的最新消息,那将是美好的。老实说,我认为这样做的每一种方式在时间和/或记忆上都会非常昂贵。想法?到目前为止,我最接近的想法是命令用户离线并构建百分比桶,但无法向用户显示其确切位置。Django:如何创建排行榜

一些代码,如果这能帮助你的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) 

回答

4

我想反击,要求用户达到最低门槛来解决这个成为排名 - 你只需要准确排序的前10%或任何。

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

它无意地获得10个用户上下文的位置500,000 - 由于指数分布,群众的排序会令人难以置信地紧张不安。编号:SO leaderboard。现在在2500(大约第20个百分点)中去page 500。用“157”代表告诉人们他们两边的10个人也代表'157'代表有什么意义?如果您的代表上升或下降一个点,您将跳过20个位置。更极端的是,现在最底部的1056页(2538页之内),或者底层42%的用户,与代表1并列。你会得到一个点,然后你跳起来1055 pages。这个数字大约增加了37,000。告诉他们“如果你再多得一分,你就可以击败三万七千人!”但是这个37k数字有多少重要数字呢?

直到你已经登顶为止,在梯子上认识你的同龄人没有任何价值,因为除了顶部之外的任何地方,都有绝大多数人。

+0

有人请编辑这个更清晰,即时睡觉。 – 2009-09-08 02:10:13

+0

我试图给用户一个目标,向他们展示他们上面的人打败,但不能太远以至于无法访问。 – 2009-09-08 02:12:12

+0

对分布底部的抖动会非常大,即使上升或下降1点也会使您下降或在1M以内获得数千个位置。你应该测量你的分数分布的样子。 – 2009-09-08 12:24:52

0

百万不是这么多,我会先试试它吧。如果points属性是你正在排序的东西,那需要成为一个数据库列。然后,您可以只计算比有问题的人更多的分数来获得排名。为了让其他人接近有问题的人,您可以查询具有更高分数的人,并按升序将其限制为您想要的人数。

棘手的事情将计算保存点。您需要使用当前时间作为奖励乘数。现在有一点需要在5天后变成小于1分的数字。如果您的用户频繁获得积分,您需要创建一个队列来处理负载。