Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude null values from Django's ArrayAgg

I'm using Django's postgres-specific ArrayAgg aggregator. It works fine but when the list is empty I get [None] instead of []. Is there any way to filter these null values out? I've tried to pass a filter argument to ArrayAgg but it didn't work. Here's a simplified example of my setup:

class Image(models.Model):
    # ...

class Reporter(models.Model):
    # ...

class Article(models.Model):
    reporter = models.ForeignKey(Reporter, related_name='articles')
    featured_image = models.ForeignKey(Image, related_name='articles')
    # ...

Then if I make this query:

reporter = Reporter.objects.annotate(
    article_images=ArrayAgg('articles__featured_image'),
    distinct=True
).first()

And the first reporter in the result set doesn't have any associated article, I get:

> reporter.article_images
[None]

I've tried to add a filter, but no luck:

Reporter.objects.annotate(
    article_images=ArrayAgg(
        'articles__featured_image',
        filter=Q(articles__featured_image__isnull=False)
    )
)
like image 936
Ariel Avatar asked Mar 11 '19 08:03

Ariel


1 Answers

I've tried your syntax Q(field__isnull=False) and also ~Q(field=None); both work fine for me on Django 2.1.7 and PG 11.2: I get [] instead of [None].

In the Django shell, you can check the SQL query that Django generates for your queryset:

print(str(your_queryset.query))

The relevant SQL portion in my test was:

ARRAY_AGG("table"."field_id") 
    FILTER (WHERE "table"."field_id" IS NOT NULL)
    AS "agg"

Depending on the syntax variant used, you can also get the following, which however works out the same:

FILTER (WHERE NOT ("table"."field_id" IS NULL))
like image 160
Endre Both Avatar answered Nov 02 '22 08:11

Endre Both