Граф агрегации Джанго - PullRequest
4 голосов
/ 14 марта 2019

Я пытаюсь отфильтровать мою модель с помощью агрегатной функции.

У меня есть модель 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 дает мне неправильный результат?

Заранее спасибо.

EDIT:

Я использую django-rest-framework и пытаюсь добавить пользовательский фильтр. ( см. Документ здесь ). Ожидаемый результат: 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

Если вам нужна дополнительная информация, дайте мне знать.

Ответы [ 2 ]

1 голос
/ 19 марта 2019

На основании опубликованного вами SQL ваши Pronostic объекты упорядочены по полю date в связанном Match объекте.Если вы удалите порядок (используя пустую order_by()), я ожидаю, что цифры совпадут.Проверьте это:

annotate_pool = queryset.order_by().annotate(nb_bets=Count('bets')).all()
1 голос
/ 14 марта 2019

Это вопрос с подвохом, если вы не показываете набор запросов для annotate_pool.

Я предполагаю, что в вашем запросе SQL для annotate_pool есть поля с Bet, в результатев дубликатах Protostic с, которые различаются только по соответствующим полям Bet, что снова приводит к меньшему количеству ставок.Тест:

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

True или False?Я предполагаю, что True (при условии, что annotate_pool не отфильтрован и содержит все Pronostic объектов).Это означает, что у вас есть дубликаты Pronostic в annotate_pool.Число Bet s распределено по этим дубликатам.

...