Django 聚合计数
Django Aggregation Count
我正在尝试使用聚合函数过滤我的模型。
我有一个模型 A 和一个模型 B,模型 A 上有一个外键。
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)
这是我的查询集中包含的 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
如果您需要更多信息,请告诉我。
只要您不显示 annotate_pool
的查询集,这就是一个技巧问题。
我的猜测是您在 SQL 查询 annotate_pool
中有来自 Bet
的字段,导致重复的 Protostic
仅通过相关 Bet
字段,这再次导致较低的投注计数。测试:
Pronostic.objects.count() < len(annotate_pool)
True
还是 False
?我的猜测是 True
(前提是 annotate_pool
未经过滤并且包含所有 Pronostic
对象)。这意味着您在 annotate_pool
中有重复的 Pronostic
。 Bet
的数量分布在这些重复项上。
根据您发布的 SQL,您的 Pronostic
对象按相关 Match
对象中的字段 date
排序。如果您删除排序(使用空 order_by()
),我希望数字匹配。测试一下:
annotate_pool = queryset.order_by().annotate(nb_bets=Count('bets')).all()
我正在尝试使用聚合函数过滤我的模型。
我有一个模型 A 和一个模型 B,模型 A 上有一个外键。
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)
这是我的查询集中包含的 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
如果您需要更多信息,请告诉我。
只要您不显示 annotate_pool
的查询集,这就是一个技巧问题。
我的猜测是您在 SQL 查询 annotate_pool
中有来自 Bet
的字段,导致重复的 Protostic
仅通过相关 Bet
字段,这再次导致较低的投注计数。测试:
Pronostic.objects.count() < len(annotate_pool)
True
还是 False
?我的猜测是 True
(前提是 annotate_pool
未经过滤并且包含所有 Pronostic
对象)。这意味着您在 annotate_pool
中有重复的 Pronostic
。 Bet
的数量分布在这些重复项上。
根据您发布的 SQL,您的 Pronostic
对象按相关 Match
对象中的字段 date
排序。如果您删除排序(使用空 order_by()
),我希望数字匹配。测试一下:
annotate_pool = queryset.order_by().annotate(nb_bets=Count('bets')).all()