Django Aggregate & Annotate Notları

Aggregate_Annotate

Django Aggregate & Annotate Notları

  • Bu yazımızda Django'da aggregate ve annotate kullanımını öğreneceğiz.
Tanımlar
  • Aggregation, bir şeyleri gruplama, kümele, bir araya getirme sürecidir. Örneklerimizde veritabanı tablolarını bir araya getirmeyi django queryset'ler ile yapacağız.
  • Annotation, bir yazıya ya da resme kısa bir açıklama ya da not eklemedir. Örneklerimizde django'daki model sınıf instance'a ekstra attribute ekleyerek kullanışlı bilgiler alacağız.

Veritabanı Modeli

AggregateAnnotate.png

 

models.py

python manage.py shell diyerek shell ortamında pratiklere başlıyoruz

Aggregate

  • Queryset sonucuna göre aggregation yapılabilir. Book.objects.all().aggregate(Avg('price')) gibi.
  • Book.objects.aggregate(Avg('price')) şeklinde de aggregation yapılabilir.
  • aggregate() key-value çiftine sahip bir dictionary return eder.
  • Aggregate değeri için manuel isim vermek isterseniz Book.objects.aggregate(ortalama_fiyat=Avg('price'))şeklinde kullanabilirsiniz. Return edilen veri {'ortalama_fiyat': 34.35} gibi olacaktır.
  • Birden fazla aggregate oluşturmak için Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) yapısını kullanabilirsiniz. Return edilen veri: {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} gibi olacaktır.

Annotate

  • Bir queryset'te her bir obje için bağımsız özet bir veri üretmek için kullanılır. Örneğin; bir kitap listesinde her bir kitaba kaç tane yazarın katkıda bulunduğunu bilmek için annotate yapısı kullanılabilir.

  • annotate() bir QuerySet return eder. Return edilen bu queryset başka bir queryset ile filter, order_by() gibi yapılar kullanılarak sorgu düzenlenebilir.

annotate ile birden fazla aggregation birleştirme

  • Subquery'ler yerine join'ler kullanıldığı için birden fazla aggregation birleştirme hatalı sonuçlar çıkarmaktadır.
  • Bir çok aggregate için bu problemi gidermenin yolu yoktur, ancak Count aggregate'e ait distinct parametresi yardımcı olabilir.

Join ve Aggregate

  • Şimdiye kadar yapılan örneklerde Model'e ait field'lar üzerinden aggregation yaptık. Ancak bazen ilişkili model'e ait field üzerinde de aggretaion yapma ihtiyacı duyarız. Django'daki double underscore __ notasyonu ile ilişkili modeldeki alanları aggregation'da kullanabiliriz.

  • Join zincirleri double underscore ile istenildigi kadar kullanılabilir.

  • Örneğin; her bir yayın evindeki en genc yazar bilgisi

 

Backward relationship aggregation

  • İlişkili modellerin lowercase sınıf adını ve double underscore notasyonunu kullanarak aggregation yapılabilir. Publisher -> Book arasındaki ilişkiyi yukarıda belirtmiştik.

  • Örneğin her bir yayınevine ait kitap sayısını öğrenmek için;

  • Ya da her bir yayınevindeki toplam kitap sayfa sayısını bulmak için

  • Bütün yayınevlerindeki en eski ve en yeni yayımlanan kitaba ait tarih bilgisini aşağıdaki gibi alabiliriz

  • Yazarların kitaplarının ortalama oranlarını aşağıdaki gibi alabiliriz

  • Yazarların kitap sayilarini almak icin

 

Aggregation ve diğer QuerySet ibareleri

  • Aggregate ile filter() veya exlude() ibaresini kullanabilirsiniz.

  • Örneğin Ç ile başlayan kitapların ortalama fiyatını aşağıdaki şekilde alabiliriz

  • Y ile başlayan her bir kitabın bulunduğu pazar yeri sayisi

  • Ç ile başlayan her kitabın bulunduğu pazar yeri sayısı

Annotation'ların filtrelenmesi

  • filter() veya exclude() ibareleri annotate ile kullanılabilir.

  • Her bir kitap satış sitesindeki kitapların adedinin bilgisi ve adedi 5'ten büyük eşit olanların bilgisi

  • Eğer 2 tane annotation'ı birleştirerek filtreleme yapacaksanız filter parametresini ve aşağıdaki yapıyı kullanabilirsiniz. Örneğin her bir yazarın kitap sayisini ve kitaplarinin oranlarindan 4.8'den buyuk ve esit olanlari almak icin;

  • filter parametresini tekil annotation ve aggregation'da kullanmak önerilmez. Bunun yerine Queryset.filter( ) yapısı kullanılmalıdır.

  • filter parametresini 2 veya daha fazla aggregation ibarelerinde farklı condition'larda kullanım önerilir.

annotate() ve filter() ibarelerinin sırası

  • Kompleks querysetler geliştirirken annotate ve filter ibarelerinin sırasına dikkat etmek gereklidir.

order_by ile annotate kullanımı

values() ile annotate kullanımı

  • Eğer values() ibaresi annotate()ibaresinden önce gelirse, annotation'lar otomatik olarak sonuç data setine eklenecektir. Ancak values(), annotate()'den sonra gelirse annotation field'ları values içerisine eklemeniz gerekmektedir.

 

Aggreating annotations

  • Annotate üzerine aggregation yapabilirsiniz.

 

Kaynak

 

 

Yorumlar