Sự khác biệt giữa phương pháp chú thích và tổng hợp của Django?


113

Django's QuerySetcó hai phương pháp, annotateaggregate. Tài liệu nói rằng:

Không giống như tổng hợp (), annotate () không phải là một mệnh đề đầu cuối. Đầu ra của mệnh đề annotate () là một QuerySet.

Có sự khác biệt nào khác giữa chúng không? Nếu không, thì tại sao aggregatetồn tại?

Câu trả lời:


186

Tôi sẽ tập trung vào các truy vấn ví dụ hơn là trích dẫn của bạn từ tài liệu. Aggregatetính toán các giá trị cho toàn bộ tập truy vấn . Annotatetính toán các giá trị tóm tắt cho từng mục trong bộ truy vấn.

Tổng hợp

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

Trả về một từ điển chứa giá trung bình của tất cả các sách trong bộ truy vấn.

Chú thích

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

q là tập hợp các cuốn sách, nhưng mỗi cuốn sách đã được chú thích với số lượng tác giả.


Tôi có chính xác rằng .annotate()trên một qs một mình không đạt được db, nhưng gọi q[0].num_authorsthì không? Tôi giả sử aggregatephải luôn nhấn db vì nó là một mệnh đề đầu cuối?

@ alias51 thực sự liên quan đến câu hỏi ban đầu, vì vậy tôi không nghĩ rằng các nhận xét về một câu hỏi tám tuổi là nơi tốt nhất để hỏi. Nếu bạn muốn kiểm tra khi nào các truy vấn chạy, thì bạn có thể kiểm traconnection.queries . Gợi ý: kiểm tra xem nó có phải là book = q[0]hoặc 'book.num_authors` gây ra truy vấn hay không.
Alasdair,

21

Đó là sự khác biệt chính, nhưng tổng hợp cũng hoạt động ở quy mô lớn hơn so với chú thích. Các chú thích vốn có liên quan đến các mục riêng lẻ trong một bộ truy vấn. Nếu bạn chạy Countchú thích trên một thứ gì đó giống như trường nhiều đến nhiều, bạn sẽ nhận được số lượng riêng cho từng thành viên của tập truy vấn (dưới dạng thuộc tính được thêm vào). Tuy nhiên, nếu bạn làm điều tương tự với một tập hợp, nó sẽ cố gắng đếm mọi mối quan hệ trên mọi thành viên của tập hợp truy vấn, ngay cả các bản sao và trả về chỉ là một giá trị.


Tôi có chính xác rằng chỉ .annotate()trên một qs không đạt đến db, nhưng gọi kết quả của một chú thích chẳng hạn như q[0].num_authorskhông? Tôi giả sử aggregatephải luôn nhấn db vì nó là một mệnh đề đầu cuối?

21

Aggregate Aggregate tạo ra các giá trị kết quả (tóm tắt) trên toàn bộ QuerySet. Tổng hợp hoạt động trên tập hợp hàng để nhận một giá trị duy nhất từ ​​tập hợp hàng. (Ví dụ: tổng của tất cả các giá trong tập hợp hàng). Aggregate được áp dụng trên toàn bộ QuerySet và nó tạo ra các giá trị kết quả (tóm tắt) trên toàn bộ QuerySet.

Trong mô hình:

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

Trong vỏ bọc:

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

Annotate Annotate tạo một bản tóm tắt độc lập cho từng đối tượng trong QuerySet. (Có thể nói nó lặp lại từng đối tượng trong QuerySet và áp dụng thao tác)

Trong mô hình:

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')

Đang xem:

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

Ở chế độ xem, nó sẽ tính số lượt thích cho mỗi video


tại sao lại distinct=Trueđược yêu cầu trong ví dụ cuối cùng?
Yuriy Leonov

@YuriyLeonov difference = True được sử dụng để thao tác thực hiện trên giá trị khác biệt. Nó không liên quan đến câu hỏi hiện tại được hỏi. Xin lỗi vì điều đó Trên thực tế tôi đã sử dụng mã của mình.
Vinay Kumar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.