Документация Django здесь не так? - PullRequest
1 голос
/ 05 октября 2019

https://docs.djangoproject.com/en/2.2/ref/models/expressions/#aggregate-expressions

Кажется, упоминаются агрегатные функции, но затем я использую аннотации в качестве примера, я схожу с ума или я чего-то здесь упускаю? У меня чертовски много времени, чтобы понять это!

1 Ответ

1 голос
/ 05 октября 2019

Вы можете использовать агрегатные функции, такие как Count [Djanog-doc] , Sum [Django-doc] и т. д. как при вызове функции .annotate(..) [Django-doc] и .aggregate(..).

Но эти два не одинаковы. .aggregate(..) означает, что мы вычисляем COUNT(*), SUM(*) и т. Д. По всему набору запросов. .aggregate(..) сделает нетерпеливый вызов базы данных и возвратит словарь, содержащий ключи, которые сопоставляются со значением, полученным из COUNT(*) и т. Д.

.annotate(..) с другой стороны, используется для создания агрегатов на объект. Так что он переведет это в запрос с GROUP BY частью. Это добавит дополнительные атрибуты к объектам модели (или другим объектам), которые возникают из набора запросов. .annotate(..) создает новый набор запросов, поэтому лениво запрашивает базу данных.

Пример : скажем, у нас есть следующая модель:

class Author(models.Model):
    name = models.CharField(max_length=128)

class Book(models.Model):
    name = models.CharField(max_length=128)
    author = models.ForeignKey(Author, on_delete=models.PROTECT)

Затем мы можем посчитать количество Book s для всех авторов с именем, которое начинается с 'Alice' с:

from django.db.models import Count

Author.objects.filter(name__startswith='Alice').aggregate(books=Count('book'))

Здесь мы, таким образом, будем получать словарь, например {'books': 1425},содержит общее количество книг, написанных Author, чье имя начинается с 'Alice'. Запрос будет выглядеть следующим образом:

SELECT COUNT(book.id) AS books
FROM author
LEFT OUTER JOIN book ON book.author_id = author.id
WHERE author.name LIKE 'Alice%'

Таким образом, мы подсчитываем все книги и получаем один результат.

Однако мы также можем использовать .annotate(..):

from django.db.models import Count

Author.objects.filter(name__startswith='Alice').annotate(books=Count('book'))

Это набор запросов, который, в случае оценки, приведет к коллекции Author с. Каждый Author, который возникает из этого набора запросов, будет иметь дополнительный атрибут .book, который содержит количество книг , которые написал автор.

Здесь запрос будеттаким образом выглядят как:

SELECT author.*, COUNT(book.id) AS books
FROM author
LEFT OUTER JOIN book ON book.author_id = author.id
WHERE author.name LIKE 'Alice%'
GROUP BY author.id
...