Django-如何在窗口表达式/注释后过滤?

时间:2019-01-30 17:18:27

标签: django annotations

我正在尝试使用Django的Window表达式来查找一堆Leaderboard对象的等级。我需要保存该排名以供以后使用,而这正是造成我麻烦的那部分。

我有一种有效的方法,但是对我来说太慢了。 (是的,我已经设置了@transaction.atomic

window = {
    'partition_by': [F('category_1'), F('category_2')],
    'order_by': F('score').desc()
}
my_filter={"condition_1":True, "condition_2": False}
ranking = Leaderboard.objects.filter(**my_filter).annotate(
    r=Window(expression=Rank(), **window)
)
for lb in ranking:
    lb.ranking = r
    lb.save()

我知道我需要摆脱保存循环并将其替换为update()调用。因此,我尝试改为这样做:

Leaderboard.objects.filter(**my_filter).update(
    ranking=Subquery(
       Leaderboard.objects.filter(**my_filter).annotate(
           rank=Window(expression=Rank(), **window)
       ).filter(
           pk=OuterRef('pk')
       ).values('rank')[:1]
    )
)

但是当我尝试此操作时,每个Leaderboard的排名都是1 ...这不是我想要的(但比以前的方法快10倍)。


我认为这是因为我对主键的筛选发生在Window表达式之前,这导致Window表达式在1个对象上运行,而不是在多个对象上运行。要运行update(),我需要能够将Subquery的结果降低到个人排名。

我觉得我被Annotations的一些简单属性所绊倒,我只是不知道什么。

0 个答案:

没有答案