Gruppieren nach UND aggregieren mit Django


82

Ich habe eine ziemlich einfache Abfrage, die ich über das ORM stellen möchte, kann das aber nicht herausfinden.

Ich habe drei Modelle:

Ort (ein Ort), Attribut (ein Attribut, das ein Ort haben könnte) und Bewertung (ein M2M-Durchgangsmodell, das auch ein Bewertungsfeld enthält)

Ich möchte einige wichtige Attribute auswählen und meine Standorte nach diesen Attributen ordnen können - dh höhere Gesamtpunktzahl über alle ausgewählten Attribute = besser.

Ich kann das folgende SQL verwenden, um das zu bekommen, was ich will:

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

was zurückkehrt

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

Das nächste, was ich mit dem ORM erreichen kann, ist:

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

Welches kehrt zurück

{'score__sum': 23}

dh die Summe aller, nicht nach Standort gruppiert.

Wie kann man das umgehen? Ich könnte die SQL manuell ausführen, würde aber lieber über das ORM gehen, um die Dinge konsistent zu halten.

Vielen Dank



Antworten:


135

Versuche dies:

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

3
hmmm - nicht aggregieren kommentieren - warum ist das so?
Guy Bowden

51
aggregateist für die vollständige Ergebnismenge annotatefür einzelne (gruppierte) Zeilen.
Bouke

'dict' object has no attribute '_meta'Weiß jemand, wie man mit einem solchen QuerySet umgeht?
Maciek

Hallo @Aamir, ich habe ein ähnliches Problem. Kannst du es dir ansehen? Link-hier
Ermir Beqiraj

Gibt so etwas wie[{"location": 53, "score": 100}, {"location": 54, "score": 104}]
Irvan

38

Kannst du das versuchen?

Rating.objects.values('location_id').filter(attribute__in=attributes).annotate(sum_score=Sum('score')).
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.