Usage Of Group_By And String_Agg In Django, Postgresql

Usage Of Group_By And String_Agg In Django, Postgresql

In this article we are going to learn how to optimize the queries in Django applications. Django has a built-in ORM which converts the django query into optimized SQL query. In some cases we need to group the data based on some common django field or a table column. This can also be done without using the group_by and string_agg in django query. In such cases we need to query for all matching records and then form the groups based on the fields. In this case we need to query first and then process the results. It will cost more time (i.e: SQL query time + Data Processing time). If we use group_by and string_agg in django with postgreSQL database, to optimize the query time and get the desired data format.

Let's consider the below models

from django.db import models

class Customer(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

class Address(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    phone = models.CharField(max_length=15)
    line = models.CharField(max_length=50)
    city = models.CharField(max_length=50)

Now, consider the below data tables

Table: Customer

id first_name last_name
1 Anji B
2 Jessi S
3 Rohan C

Table: Address

id customer_id phone line city
1 1 987654321 sri nagar Hyderabad
2 2 123654789 sai nagar Bangalore
3 1 987456321 prakash nagar Medak
4 1 321456987 Joshenbeg Rangareddy

Desired Data Format:

customer_id customer_name phone_numbers
1 Anji 987654321, 987456321, 321456987
2 Jessi 123654789

To get data format like above table we need use group_by and string_agg in django with postgreSQL database. Let's see the below django query

from django.db.models import F
from django.contrib.postgres.aggregates.general import StringAgg

queryset = Address.objects.values('customer_id').order_by('customer_id').annotate(
    phone_numbers=StringAgg('phone', delimiter=','),
    customer_name=F('customer__first_name')
)
print(queryset)
# Output: <QuerySet [{'phone_numbers': '987654321,987456321,321456987',
# 'customer_name': 'Anji', 'customer_id': 1},
# {'phone_numbers': '123654789', 'customer_name': 'Jessi',
# 'customer_id': 2}]>

Try above code to test it practically in your project.

References:
https://docs.djangoproject.com/en/dev/_modules/django/contrib/postgres/aggregates/general/#StringAgg