Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting distinct elements in Django ArrayField

Tags:

django

I have a model defined by

from django.contrib.postgres.fields import ArrayField

class Model(models.Model):
    name = models.CharField(max_length=255)
    tags = ArrayField(models.CharField(max_length=255))

I would like a way to efficiently grab the count of each distinct element in my tags ArrayField. I put together this piece of code to do try to do that.

Model.objects.annotate(elems=Func(F('tags'), function='unnest')).values_list('elems', flat=True).annotate(c=Count('elems'))

But it returns an error

...aggregate function calls cannot contain set-returning function calls
LINE 1: ...COUNT(unnest("...
                 ^
HINT:  You might be able to move the set-returning function into a LATERAL FROM item.

Any ideas on how to make this query work?

Edit

This is the SQL that Django's ORM generates.

SELECT unnest("model"."tags") AS "elems", COUNT(unnest("model"."tags")) AS "c" FROM "model" GROUP BY unnest("model"."tags");
like image 763
Will Meyers Avatar asked Oct 23 '25 23:10

Will Meyers


1 Answers

This query worked for me:

select unnest(tags) as tag, count(tags) from model group by tag;

I think this ORM query gives the same result:

from django.db.models import Func, F, Count

Model.objects.annotate(tag=Func(F('tags'), function='unnest')).values('tag').order_by('tag').annotate(count=Count('id')).values_list('tag', 'count')

I have created the following table and populated with sample values:

create table model(
    id serial primary key,
    name text,
    tags text[]
);

insert into model(name, tags) values ('a', array['a', 'b', 'c']);
insert into model(name, tags) values ('b', array['b', 'b', 'c']);

select unnest(tags) as tag, count(tags) from model group by tag;

+---+-----+
|tag|count|
+---+-----+
|c  |2    |
|a  |1    |
|b  |3    |
+---+-----+
like image 91
maksadbek Avatar answered Oct 25 '25 13:10

maksadbek