web-dev-qa-db-fra.com

Différence entre les méthodes d'annotation et d'agrégation de Django?

QuerySet de Django a deux méthodes, annotate et aggregate. La documentation indique que:

Contrairement à l'agrégat (), annotate () n'est pas une clause terminale. La sortie de la clause annotate () est un QuerySet.

Y a-t-il une autre différence entre eux? Sinon, pourquoi existe-t-il aggregate?

93

Je me concentrerais sur les exemples de requêtes plutôt que sur votre citation de la documentation. Aggregate calcule les valeurs de l'ensemble de requêtes entier. Annotate calcule les valeurs récapitulatives pour chaque élément dans le jeu de requêtes.

Agrégation

>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}

Renvoie un dictionnaire contenant le prix moyen de tous livres dans l'ensemble de requêtes.

Annotation

>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

q est l'ensemble de requêtes des livres, mais chaque livre a été annoté avec le nombre d'auteurs.

153
Alasdair

C'est la principale différence, mais les agrégats fonctionnent également à une échelle plus grande que les annotations. Les annotations sont intrinsèquement liées aux éléments individuels d'un ensemble de requêtes. Si vous exécutez une annotation Count sur quelque chose comme un champ plusieurs-à-plusieurs, vous obtiendrez un décompte distinct pour chaque membre de l'ensemble de requêtes (en tant qu'attribut ajouté). Si vous deviez faire la même chose avec une agrégation, cependant, elle essaierait de compter chaque relation sur chaque membre du jeu de requêtes, même les doublons, et de le renvoyer comme une seule valeur.

18
Chris Pratt

Aggregate Aggregate génère des valeurs de résultat (résumé) sur un QuerySet entier. Les agrégats opèrent sur l'ensemble de lignes pour obtenir une valeur unique de l'ensemble de lignes (par exemple, la somme de tous les prix de l'ensemble de lignes). L'agrégat est appliqué à l'ensemble du QuerySet et il génère des valeurs de résultat (récapitulatif) sur un QuerySet entier.

Dans le modèle:

class Books(models.Model):
    name = models.CharField(max_length=100)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=3)

En coquille:

>>> Books.objects.all().aggregate(Avg('price'))
# Above code will give the Average of the price Column 
>>> {'price__avg': 34.35}

Annotate Annotate génère un résumé indépendant pour chaque objet dans un QuerySet. (On peut dire qu'il itère chaque objet dans un QuerySet et applique une opération)

Dans le modèle:

class Video(models.Model):
    name = models.CharField(max_length=52, verbose_name='Name')
    video = models.FileField(upload_to=document_path, verbose_name='Upload 
               video')
    created_by = models.ForeignKey(User, verbose_name='Created by', 
                       related_name="create_%(class)s")
    user_likes = models.ManyToManyField(UserProfile, null=True, 
                  blank=True, help_text='User can like once', 
                         verbose_name='Like by')

En vue:

videos = Video.objects.values('id', 'name','video').annotate(Count('user_likes',distinct=True)

En vue, il comptera les likes pour chaque vidéo

11
Vinay Kumar