簡體   English   中英

Django 通過謂詞和計數結果注釋查詢集

[英]Django annotate queryset by predicate and count results

我有兩個模型:

class Game(models.Model):
    id = models.AutoField(primary_key=True)


class Score(models.Model):
    id = models.AutoField(primary_key=True)
    game = models.ForeignKey(Game, related_name="score", on_delete=models.CASCADE)
    first_score = models.IntegerField(blank=True)
    second_score = models.IntegerField(blank=True)
    is_rusk = models.BooleanField(blank=True)

我得到了一個游戲對象的查詢集:

[
    {
        "id": 314317035,
        "score": [
            {
                "first_score": 5,
                "second_score": 1,
                "is_rusk": false
            }
        ]
    },
    {
        "id": 311298177,
        "score": [
            {
                "first_score": 5,
                "second_score": 2,
                "is_rusk": false
            }
        ]
    },
    {
        "id": 310278749,
        "score": [
            {
                "first_score": 5,
                "second_score": 2,
                "is_rusk": false
            }
        ]
    },
    {
        "id": 309866238,
        "score": [
            {
                "first_score": 5,
                "second_score": 0,
                "is_rusk": true
            }
        ]
    },
    {
        "id": 307926664,
        "score": [
            {
                "first_score": 5,
                "second_score": 0,
                "is_rusk": true
            }
        ]
    },
    {
        "id": 306047964,
        "score": [
            {
                "first_score": 4,
                "second_score": 5,
                "is_rusk": false
            }
        ]
    },
    {
        "id": 304881611,
        "score": [
            {
                "first_score": 5,
                "second_score": 3,
                "is_rusk": false
            }
        ]
    },
    {
        "id": 304468136,
        "score": [
            {
                "first_score": 5,
                "second_score": 2,
                "is_rusk": false
            }
        ]
    },
]

我想用rusks_cnt注釋這個查詢集,它將是帶有is_rusk=True的對象的計數,如果有辦法不將它添加到每個 object 中,就像一個字段一樣,那也很好。

我認為最簡單的方法是這樣的:

cnt = queryset.filter(score__is_rusk=True).count()

但是當我試圖這樣注釋時:

cnt = queryset.filter(score__is_rusk=True).count()
queryset = queryset.annotate(cnt=cnt)

它說:

QuerySet.annotate() received non-expression(s): 2.

我也試過:

queryset = queryset.annotate(
         rusk_cnt=Sum(
                Case(When(score__is_rusk=True, then=1)), output_field=IntegerField()
            )
        )

但結果是:

[
    {
        "id": 279658929,
        "rusk_cnt": 1
    },
    {
        "id": 279796553,
        "rusk_cnt": null
    },
    ...
]

另外我想知道只是使用.count()會導致性能不佳嗎?

您可以使用Value進行注釋:

from django.db.models import Value

cnt = queryset.filter(score__is_rusk=True).count()
queryset = queryset.annotate(cnt=Value(cnt))

但這將添加相同的值:查詢集中GameScore對象的queryset所有Game對象,這沒有多大意義。

如果您想用True注釋Game對象,使用is_rusk=True Score的對象數量,您可以使用:

from django.db.models import Q, Sum

queryset.annotate(
    rusk_cnt=Sum('score', filter=Q(score__is_rusk=True))
)

Annotate 用於計算每個條目。 如果要計算整個查詢集,請使用聚合。

Django的注釋和聚合方法之間的區別?

暫無
暫無

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

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