聚合和注释与信号的效率

时间:2012-08-19 17:21:46

标签: django aggregate django-aggregation

我想计算用户对我网站的贡献数量,以便我可以在网站上对其进行排名。我设法编写了一些完美的代码,但是基于每个用户。

由于用户获得不同字段的不同点数,因此会检查模型上的某些字段以及用户是否在其中放置了值。然后将它们与它们的权重相乘以得出总分。

没有什么比一些代码更好:

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信号。然后使用我现有的类重新计算用户的点数,并将其存储在用户配置文件中。这样我就可以按照个人资料中的值对用户进行排序,这很简单。

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

提前致谢,

tBuLi

1 个答案:

答案 0 :(得分:0)

我想说这取决于您的模型更改的频率以及您的前10名需要的准确性和最新性。对于它的价值,您可以将前10名缓存一小时甚至一天。另一方面,如果你不得不做一些django聚合没有涵盖的复杂排序或处理 - 你将受益于非规范化。

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