Подсчет отдельных элементов в Django ArrayField - PullRequest
1 голос
/ 01 августа 2020

У меня есть модель, определенная как

from django.contrib.postgres.fields import ArrayField

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

. Мне нужен способ эффективного получения количества каждого отдельного элемента в моих тегах ArrayField. Я собрал этот фрагмент кода, чтобы попытаться это сделать.

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

Но он возвращает ошибку

...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.

Есть идеи, как заставить этот запрос работать?

Изменить

Это SQL, который генерирует ORM Django.

SELECT unnest("model"."tags") AS "elems", COUNT(unnest("model"."tags")) AS "c" FROM "model" GROUP BY unnest("model"."tags");

1 Ответ

1 голос
/ 01 августа 2020

У меня сработал этот запрос:

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

Если честно, я не знаю, как преобразовать его в Django ORM. Не стесняйтесь редактировать этот ответ, чтобы добавить его.

Но вы можете выполнить этот запрос в Django:

from django.db.models import Func, F

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

Я создал следующую таблицу и заполнил ее образцами значений:

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    |
+---+-----+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...