Джанго - Как фильтровать после выражения окна / аннотации? - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь использовать выражения окна Джанго, чтобы найти ранг группы 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 результаты были доведены до ранга отдельного человека.

Мне кажется, что меня запутало какое-то простое свойство аннотаций, япросто не знаю что.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...