DjangoBrothers BLOG ✍️

2018/07/24

このエントリーをはてなブックマークに追加
Django モデル クエリセット

データの個数や最高値、平均値を取得してみよう

アグリゲーション(Aggregation)ってなに?

アグリゲーションとは、データベースに格納されているデータの個数、平均値、最高値などを調べてくれる機能のことです。Aggregationは「集計」を意味します。

データベースの中から、欲しい情報を取得するときに重宝します。

今回は以下のような例のモデルを使います。値段や評価フィールドを持つBookオブジェクトがあり、BookオブジェクトはAuthorオブジェクトと紐づいています。

models.py

from django.db import models

class Author(models.Model):
    name = models.CharField('名前', max_length=190)

    def __str__(self):
        return self.name

class Book(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    title = models.CharField('タイトル', max_length=190)
    price = models.IntegerField('値段')
    rating = models.FloatField('評価')

    def __str__(self):
        return self.title

上のモデルから、適当にいくつかのBookインスタンスを作成しました。(下図)このデータを使って、集計処理を行ってみたいと思います。

オブジェクトの数を数える(Count)

Bookオブジェクトの数を調べる

Book.objects.all().count()
# 6

最高値を抽出する(Max)

1番高い値段を調べる

from django.db.models import Max

Book.objects.all().aggregate(Max('price'))
# {'price__max': 1500}

平均値を算出する(Avg)

川端康成の評価平均値を求める

from django.db.models import Avg

Book.objects.filter(author__name='川端康成').aggregate(Avg('rating'))
# {'rating__avg': 3.0}

フィールドごとに集計する(annotate)

annotateは、新たなフィールドを生成してくれるイメージです。

下の例では、book__count、published_booksというフィールドを生成し、各Authorと紐づいているBookオブジェクトの数がわかるようになっています。

Authorが出版したBookの数を調べる

from django.db.models import Count

# クエリセットを生成
authors = Author.objects.all().annotate(Count('book'))
# <QuerySet [<Author: 川端康成>, <Author: 芥川龍之介>, <Author: 太宰治>]>

# 上で作成したクエリセットのインスタンスは、book__countというプロパティを持つ
authors[0].book__count
# 3

# 下記のように、フィールド名を指定することもできる
authors = Author.objects.all().annotate(published_books=Count('book'))
authors[0].published_books
# 3

保有するオブジェクト数順に並べる(annotate)

annotateで生成された、フィールドを使って並び替えができる。

出版したBookの数が多い順にAuthorを並べる

from django.db.models import Count

authors = Author.objects.all().annotate(Count('book')).order_by('-book__count')
# <QuerySet [<Author: 川端康成>, <Author: 芥川龍之介>, <Author: 太宰治> ]>

上の例では、出版した本が多い順にAuthorを並び替えたクエリセットを作成しています。

もっと詳しい情報が知りたい場合は こちらから