簡體   English   中英

Django中的自引用聚合

[英]Self-referential aggregation in django

是否可以在Django中編寫自引用聚合?

例如,給定以下模型定義:

from django.db import models

class Match(models.Model):
    match_id = models.BigIntegerField(primary_key=True)
    start_time = models.DateTimeField()
    league = models.ForeignKey(League, on_delete=models.CASCADE)
    team = models.ForeignKey(Team, on_delete.models.CASCADE)

我想用先前的匹配數注釋每個Match對象。 (並最終在其他條件下,例如,與給定團隊比賽的先前比賽。)

我最初的想法是:

from django.db.models import Q, F, Count

matches = Match.objects.filter(team__name='xyz')

matches.annotate(
    prior_matches=Count('match_id', filter=(
        Q(start_time__lt=F('start_time')
    ))
)

不幸的是,這似乎為所有對象提供了prior_matches=0

這個問題建議遵循一個外鍵並使用反向關系,但這似乎很笨拙,而且還存在兩個問題:

  1. 這不是嚴格等效的。 例如,以下代碼段有效,但將計算給定聯賽中而不是整體中的先前比賽。 我猜您可以通過創建一個占位符模型來解決此問題,該占位符模型將所有Match對象都用作外鍵,但這似乎並不理想。

matches.annotate(
     prior_matches=Sum(Case(
         When(start_time__lt=F('league__matches__start_time'), then=1),
         default=0,
         output_field=models.IntegerField()
     ))
)
  1. 所提供的計數是相對於數據庫中所有先前的匹配的,而不僅僅是過濾后的查詢集中的那些。 例如,上面的代碼中發現所有先前的匹配計數,盡管matches的queryset過濾特定的團隊。 我想不出一個好辦法(除了重復在每個Q / filter子句中應用到queryset的完整過濾條件外,這在管理器中無法普遍使用)。

為了避免xy問題,為了在數據庫級別工作,我希望替換的(偽)代碼片段之一如下:

def generate_stats(match):
    matches = Match.objects.filter(start_time__lt=match.start_time)

    for team in (match.home_team, match.away_team):
        q_involving = Q(home_team=team) | Q(away_team=team)
        team_matches = matches.filter(q_involving)

        team_matches.aggregate(...)  # get stats

我認為您應該將第一個代碼更改為

from django.db import models

class Match(models.Model):
    match_id = models.AutoField(primary_key=True)
    start_time = models.DateTimeField()
    league = models.ForeignKey(League, on_delete=models.CASCADE)
    team = models.ForeignKey(Team, on_delete.models.CASCADE)

否則,可能是您尚未真正添加“匹配”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM