0

我想计算用户对我的网站所做的贡献数量,以便我可以在网站上对他们进行排名。我设法编写了一些漂亮的代码来做到这一点,但基于每个用户。

因为用户在不同的字段中获得不同数量的积分,所以它会检查模型上的某些字段以及用户是否在其中输入了值。然后将这些值乘以它们的权重,得出总分。

没有什么比一些代码更能说明问题了:

class UserContribCounter(object):
    """Can count the number of points a user got for his contributions"""
    weight_dict = {'poster':2, 'title':1}

    def __init__(self, user):
        if isinstance(user, User):
            self.user = user
        else:
            raise Exception('Not a valid user instance.')

    def set_contrib_points(self):
        """Some dark magic counts the number of times a certain field was filled out"""
        self.unweighted = Movie.objects.filter(user = self.user).aggregate(poster=Count('poster'),title=Count('title'))

    def get_contrib_points(self):
        """Multiplies the number of times a field was filled out with their weights to calculate the total number of points"""
        try:
            self.unweighted
        except AttributeError:
            self.set_contrib_points()

        return sum([self.weight_dict[key] * value for key, value in self.unweighted.items()])

我还想展示前10名,所以我需要获得前10名用户。这意味着我要么必须编写一个复杂的聚合,但目前我一直没有这样做,或者我可以通过以下方式使用信号:

当模型被保存时,捕获 post_save 信号。然后使用我现有的课程为用户重新计算积分,并将其存储在用户个人资料中。这样我就可以按用户个人资料中的值对用户进行排序,这很简单。

问题是,每次保存模型时重新计数或相当复杂的聚合函数会更有效。我知道这将取决于很多事情,但我确信从概念的角度来看,应该有理由选择其中之一。请注意,我将在聚合中检查的一些字段也将是关系的,所以我不确定这将如何影响性能。

提前致谢,

叔丁基锂

4

1 回答 1

0

我想说这取决于您的模型更改的频率以及您的前 10 名需要多准确和最新。对于它的价值,您可以将前 10 名缓存一个小时甚至一天。另一方面,如果您必须进行一些 django 聚合未涵盖的复杂排序或处理,您将从非规范化中受益。

最后,这一切都归结为实际发现现实世界使用中的瓶颈。认真地先做最小的事情。

于 2012-08-20T05:15:11.457 回答