Djangoでグループ化して集約する方法


83

ORMを介して作成したい非常に単純なクエリがありますが、それを理解できません。

私は3つのモデルを持っています:

場所(場所)、属性(場所が持つ可能性のある属性)、および評価(スコアフィールドも含むM2M 'から'モデル)

いくつかの重要な属性を選択し、それらの属性によって自分の場所をランク付けできるようにしたい-つまり、選択したすべての属性よりも合計スコアが高い=より良い。

次のSQLを使用して、必要なものを取得できます。

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

戻る

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

ORMで取得できる最も近いものは次のとおりです。

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

どちらが戻る

{'score__sum': 23}

つまり、場所ごとにグループ化されていない、すべての合計です。

これを回避する方法はありますか?SQLを手動で実行することもできますが、一貫性を保つためにORMを使用したいと思います。

ありがとう



回答:


136

これを試して:

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

3
うーん-集約ではなく注釈を付ける-それはなぜですか?
ガイボーデン

51
aggregateannotate個々の(グループ化された)行の完全な結果セット用です。
Bouke 2013年

誰かがその'dict' object has no attribute '_meta'ようなQuerySetを回避する方法を知っていますか?
maciek 2016

こんにちは@Aamir、私は同様の問題を抱えています、あなたはそれを見ることができますか?リンク-ここ
Ermir Beqiraj 2018

次のようなものを返します [{"location": 53, "score": 100}, {"location": 54, "score": 104}]
Irvan 2018年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.