Django聚合计数

问题描述 投票:4回答:2

我正在尝试使用聚合函数过滤我的模型。

我在模型A上有一个带有外键的A型和B型。

annotate_pool = queryset.annotate(nb_bets=Count('bets')).all()
for obj in annotate_pool:
    bets_obj = obj.bets.all()
    bets_length = len(bets_obj)
    print(obj.nb_bets, bets_length)

并且注释不会给我与函数长度相同的结果。

1 1
1 2
1 2
1 2
1 2
1 1
1 1
2 2

这是我的模特:

class Pronostic(models.Model):
    cote_total = models.FloatField(default=0.0)
    trust = models.IntegerField()
    mise_ratio = models.IntegerField(default=10)
    safe = models.BooleanField(default=False)

class Bet(models.Model):
    name = models.CharField(max_length=255)
    match = models.ForeignKey('pronostics.Match', on_delete=models.CASCADE, related_name='bets')
    cote = models.FloatField()
    status = models.IntegerField(choices=STATUS, default=0)
    pronostic = models.ForeignKey('pronostics.Pronostic', related_name='bets', on_delete=models.CASCADE)

len(bets_obj)应该给我与Count('bets')相同的结果。到底是怎么回事?为什么Count给我一个错误的结果?

先感谢您。

编辑:

我正在使用django-rest-framework,并尝试添加自定义过滤器。 (see doc here)。预期的结果是:obj.nb_bets应该等于bets_length。因为我想像这样过滤我的模型:

queryset.annotate(nb_bets=Count('bets')).filter(nb_bets__gte=2)

要么

queryset.annotate(nb_bets=Count('bets')).filter(nb_bets__lte=2)

这是我的queryset中包含的SQL查询:

SELECT "pronostics_pronostic"."id",
       "pronostics_pronostic"."cote_total",
       "pronostics_pronostic"."trust",
       "pronostics_pronostic"."mise_ratio",
       "pronostics_pronostic"."safe"
FROM "pronostics_pronostic"
LEFT OUTER JOIN "pronostics_bet" 
       ON ("pronostics_pronostic"."id" = "pronostics_bet"."pronostic_id")
LEFT OUTER JOIN "pronostics_match" 
       ON ("pronostics_bet"."match_id" = "pronostics_match"."id")
WHERE ("pronostics_pronostic"."visible" = TRUE
       AND "pronostics_pronostic"."safe" = TRUE)
ORDER BY "pronostics_match"."date" DESC

如果您需要更多信息,请告诉我们。

sql django django-models django-rest-framework django-orm
2个回答
1
投票

根据您发布的SQL,您的Pronostic对象按字段date在相关的Match对象中排序。如果你删除顺序(使用空的order_by()),我希望数字匹配。测试一下:

annotate_pool = queryset.order_by().annotate(nb_bets=Count('bets')).all()

1
投票

只要您不显示annotate_pool的查询集,这就是一个技巧问题。

我的猜测是你在Bet的SQL查询中有来自annotate_pool的字段,导致重复的Protostics仅由相关的Bet字段区分,这再次导致更低的下注数。测试:

Pronostic.objects.count() < len(annotate_pool)

TrueFalse?我的猜测是True(前提是annotate_pool未经过滤并包含所有Pronostic物体)。这意味着你在Pronostic中有重复的annotate_pools。 Bets的数量分散在那些重复数据上。

© www.soinside.com 2019 - 2024. All rights reserved.