Jak grupować przez AND agregować za pomocą Django


83

Mam dość proste zapytanie, które chciałbym wykonać za pośrednictwem ORM, ale nie mogę tego rozgryźć.

Mam trzy modele:

Lokalizacja (miejsce), atrybut (atrybut, który może mieć miejsce) i ocena (model M2M „do”, który zawiera również pole punktacji)

Chcę wybrać kilka ważnych atrybutów i móc uszeregować moje lokalizacje według tych atrybutów - tj. Wyższy wynik całkowity dla wszystkich wybranych atrybutów = lepszy.

Mogę użyć następującego SQL, aby uzyskać to, czego chcę:

select location_id, sum(score) 
    from locations_rating 
    where attribute_id in (1,2,3) 
    group by location_id order by sum desc;

który powraca

 location_id | sum 
-------------+-----
          21 |  12
           3 |  11

Najbliższe, co mogę uzyskać dzięki ORM, to:

Rating.objects.filter(
    attribute__in=attributes).annotate(
    acount=Count('location')).aggregate(Sum('score'))

Który powraca

{'score__sum': 23}

tj. suma wszystkich, nie pogrupowanych według lokalizacji.

Jakoś to obejść? Mógłbym wykonać SQL ręcznie, ale wolałbym przejść przez ORM, aby zachować spójność.

Dzięki



Odpowiedzi:


136

Spróbuj tego:

Rating.objects.filter(attribute__in=attributes) \
    .values('location') \
    .annotate(score = Sum('score')) \
    .order_by('-score')

3
hmmm - adnotacja nie agregacja - dlaczego tak jest?
Guy Bowden

51
aggregatedotyczy pełnego zestawu wyników annotatedla pojedynczych (zgrupowanych) wierszy.
Bouke,

czy ktoś wie, jak obejść 'dict' object has no attribute '_meta'taki zestaw QuerySet?
maciek

Cześć @Aamir, mam podobny problem, możesz na to spojrzeć? link-tutaj
Ermir Beqiraj

Zwraca coś w stylu[{"location": 53, "score": 100}, {"location": 54, "score": 104}]
Irvan

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.