Django Aggregation 집선

9040 단어 django
현재 수요에 따라 끊임없이 조정되는 응용 프로그램에서는 알파벳 순서나 창설 날짜 등 일반적인 필드를 따라 항목을 정렬할 수 있을 뿐만 아니라 다른 어떤 동적 데이터에 따라 항목을 정렬해야 한다.Djngo 집합은 이러한 요구를 충족시킬 수 있다.
다음 모델의 경우
from django.db import models



class Author(models.Model):

    name = models.CharField(max_length=100)

    age = models.IntegerField()



class Publisher(models.Model):

    name = models.CharField(max_length=300)

    num_awards = models.IntegerField()



class Book(models.Model):

    name = models.CharField(max_length=300)

    pages = models.IntegerField()

    price = models.DecimalField(max_digits=10, decimal_places=2)

    rating = models.FloatField()

    authors = models.ManyToManyField(Author)

    publisher = models.ForeignKey(Publisher)

    pubdate = models.DateField()



class Store(models.Model):

    name = models.CharField(max_length=300)

    books = models.ManyToManyField(Book)

    registered_users = models.PositiveIntegerField()


빠른 이해
# books   .

>>> Book.objects.count()

2452



# Total number of books with publisher=BaloneyPress

>>> Book.objects.filter(publisher__name='BaloneyPress').count()

73



# books   price.

>>> from django.db.models import Avg

>>> Book.objects.all().aggregate(Avg('price'))

{'price__avg': 34.35}



# books   price.

>>> from django.db.models import Max

>>> Book.objects.all().aggregate(Max('price'))

{'price__max': Decimal('81.20')}



# All the following queries involve traversing the Book<->Publisher

# many-to-many relationship backward



#    publisher   num_books  ,   pulisher   book   .

>>> from django.db.models import Count

>>> pubs = Publisher.objects.annotate(num_books=Count('book'))

>>> pubs

[<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]

>>> pubs[0].num_books

73



#   num_book    .

>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]

>>> pubs[0].num_books

1323


Generating aggregates over a QuerySet 모음 생성
Django는 집합을 생성하는 두 가지 방법이 있습니다.첫 번째 방법은 전체 QuerySet에 집합 값을 생성하는 것입니다. 예를 들어 모든 책의 price 평균 값을 생성하는 것입니다.
>>> from django.db.models import Avg

>>> Book.objects.all().aggregate(Avg('price'))

{'price__avg': 34.35}


다음과 같이 요약할 수 있습니다.
>>> Book.objects.aggregate(Avg('price'))

{'price__avg': 34.35}


함수aggregate()의 매개 변수는 일련의 집합 함수aggregate functions:
Avg
평균값 반환
Count  class Count(field, distinct=False)
카운트를 반환합니다.distinct=True 매개 변수가 있으면 unique의 객체 수를 반환합니다.
Max
최대값 반환
Min
최소값을 반환합니다.
StdDev class StdDev(field, sample=False) 표준 편차 반환
Sample 매개 변수가 있습니다.
기본적으로 Sample=False는 전체 표준 편차를 되돌려줍니다. Sample=True라면 샘플 표준 편차를 되돌려줍니다.
Sum
반환 총액
Variance class Variance(field, sample=False) 반환 분산
기본적으로 전체 방차를 되돌려주는 매개 변수 Sample이 있습니다. Sample이True로 설정되었을 때 샘플 방차를 되돌려줍니다.
aggregate () 방법이 호출되었을 때 키 값을 사전으로 되돌려줍니다. 키의 이름을 지정할 수 있습니다.
>>> Book.objects.aggregate(average_price=Avg('price'))

{'average_price': 34.35}


만약 여러 개의 집합을 만들고 싶다면, 다른 매개 변수를 추가하기만 하면 된다.그래서 만약에 우리가 모든 책의 최고와 최저 가격을 알고 싶다면:
>>> from django.db.models import Avg, Max, Min

>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))

{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}


쿼리 세트의 각 객체에 대한 집계 값 생성Generating aggregates for each item in a QuerySet
이것은 집합 값을 생성하는 두 번째 방법이다.예를 들어 너는 책마다 몇 명의 작가가 있는지 검색해야 한다.책과 author는 manytomany의 관계로 책마다 이런 관계를 정리할 수 있다.
각 객체의 요약은 다음과 같은 방법으로 annotate()를 생성할 수 있습니다.
#     annotate QuerySet

>>> from django.db.models import Count

>>> q = Book.objects.annotate(Count('authors'))

#      

>>> q[0]

<Book: The Definitive Guide to Django>

>>> q[0].authors__count

2

#      

>>> q[1]

<Book: Practical Django Projects>

>>> q[1].authors__count

1


생성된 속성의 이름을 지정할 수도 있습니다.
>>> q = Book.objects.annotate(num_authors=Count('authors'))

>>> q[0].num_authors

2

>>> q[1].num_authors

1


aggregate () 와 달리 annotate () 의 출력은QuerySet입니다.
통합 클러스터 Joins and aggregates
지금까지 저희가 조회를 모은field는 모두 저희가 조회하고자 하는 모델에 속했고 다른 모델의field로 조회를 모을 수 있습니다. 예를 들어 다음과 같습니다.
>>> from django.db.models import Max, Min

>>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price'))


이렇게 하면 모든 스토어에서 책의 가격 범위를 조회할 수 있다
연결 체인의 깊이는 다음과 같습니다.
>>> Store.objects.aggregate(youngest_age=Min('books__authors__age'))


역관계Following relationships backwards
책갈피를 사용하여 publisher를 반대로 질의하려면 다음과 같이 하십시오.
>>> from django.db.models import Count, Min, Sum, Avg

>>> Publisher.objects.annotate(Count('book'))


되돌아오는 QuerySet의 모든publisher는 속성bookcount.
가장 오래 출판된 책의 출판 날짜를 조회하다.
>>> Publisher.objects.aggregate(oldest_pubdate=Min('book__pubdate'))


각 저자가 쓴 책의 총 페이지 수를 조회하려면 다음과 같이 하십시오.
>>> Author.objects.annotate(total_pages=Sum('book__pages'))


모든 저자가 쓴 책의 평균 rating 조회:
>>> Author.objects.aggregate(average_rating=Avg('book__rating'))


집계 및 기타 쿼리 세트 작업Aggregations and other QuerySet clauses
filter() and exclude()
집합은 Filter 및 exclude와 함께 사용할 수 있습니다.
>>> from django.db.models import Count, Avg

>>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors'))

>>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price'))


집계 값을 기준으로 필터링할 수 있습니다.
>>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)


annotate () 와 Filter () 종문을 포함하는 복잡한 검색어를 작성할 때QuerySet에 작용하는 종문의 순서에 따라 의미가 다르다는 것을 주의해야 한다.
>>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0)

>>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))


두 조회 모두 적어도 좋은 책 한 권 (평점이 3점 이상) 을 출판한 출판사의 목록을 되돌려 주었다.그러나 첫 번째 조회의 주석은 출판사가 발행한 모든 도서의 총수를 포함한다.두 번째 조회의 주해는 좋은 책을 출판한 출판사의 발행된 좋은 책(평점 3점 이상) 총수만 포함한다.첫 번째 질의에서 주석은 필터 앞에 있기 때문에 필터는 주석에 영향을 주지 않습니다.두 번째 조회에서 필터는 주해 전에 있기 때문에 주해 값을 계산할 때 필터는 연산에 참여하는 대상의 범위를 제한한다
order_by()
집계 값을 기준으로 정렬할 수 있습니다.
>>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')


values()
일반적으로 주해 annotate는 모든 대상에 추가되며, 주해 작업을 수행한 조회 집합QuerySet이 되돌아오는 결과에 모든 대상에 주해 값이 추가됩니다.그러나values () 종문을 사용하면 결과의 범위를 제한하고 주석에 값을 부여하는 방법은 완전히 달라집니다.원시적인QuerySet 반환 결과에 모든 대상에 주석을 추가하는 것이 아니라,values () 문장에 정의된 필드 조합에 따라 선결과의 유일한 그룹을 나누고, 그룹마다 주석값을 산출합니다. 이 주석값은 그룹의 모든 구성원에 따라 계산됩니다.
>>> Author.objects.values('name').annotate(average_rating=Avg('book__rating'))


이러한 쓰기 방법에서QuerySet은name에 따라 조합되며, 모든 unique name의 집합 값을 되돌려줍니다.만약 두 작가가 같은 이름을 가지고 있다면, 이 두 작가는 하나의 계산으로 여겨져 그들의 책과 함께 모일 것이다.
>>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rating')


위치가 바뀌면 모든 author에averagerating, 그리고 모든 author의name와average 만 출력합니다.rating.
기본 정렬에서는 다음과 같은 집합을 사용합니다.
from django.db import models



class Item(models.Model):

    name = models.CharField(max_length=10)

    data = models.IntegerField()



    class Meta:

        ordering = ["name"]


중복되지 않은 데이터 값이 나타나는 횟수를 알고 싶으면 다음과 같이 쓸 수 있습니다.
# Warning:       

Item.objects.values("data").annotate(Count("id"))


이 부분의 코드는 공통된 데이터 값을 사용하여 Item 대상을 그룹화한 다음 그룹마다 id 값의 총수를 얻으려고 합니다.하지만 위에서 그렇게 하는 것은 통하지 않는다.기본 정렬 항목의name도 하나의 그룹 항목이기 때문에, 이 검색은 중복이 아닌 (data,name) 에 따라 그룹을 나눈다. 이것은 당신이 원하던 결과가 아니다.따라서 기본 정렬의 영향을 제거하려면 다음과 같이 써야 합니다.
Item.objects.values("data").annotate(Count("id")).order_by()


Aggregating annotations
또한 annotation 결과에 따라 집합 값을 생성할 수 있다. 예를 들어 책마다 평균 몇 명의 저자가 있는지 계산할 수 있다.
>>> from django.db.models import Count, Avg

>>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors'))

{'num_authors__avg': 1.66}


좋은 웹페이지 즐겨찾기