Django Postgres ArrayField聚合和过滤

时间:2016-04-20 11:27:01

标签: django postgresql django-contrib

继续这个问题:Django Postgresql ArrayField aggregation

我有ArrayField个类别,我想检索它拥有的所有唯一值 - 但是应该过滤结果,以便只返回以提供的字符串开头的值。

"大多数Django"这样做的方式?

给定Animal模型,如下所示:

class Animal(models.Model):
    # ...
    categories = ArrayField(
        models.CharField(max_length=255, blank=True),
        default=list,
    )
    # ...

然后,根据the other question's answer,这适用于查找未经过滤的所有类别。

all_categories = (
    Animal.objects
    .annotate(categories_element=Func(F('categories'), function='unnest'))
    .values_list('categories_element', flat=True)
    .distinct()
)

但是,现在,当我尝试过滤结果时,我失败了,不只是__startswith而是所有类型的filter

all_categories.filter(categories_element__startswith('ga'))
all_categories.filter(categories_element='dog')

stacktrace的底部是:

DataError: malformed array literal: "dog"
...
DETAIL:  Array value must start with "{" or dimension information.

...而且它似乎是因为Django试图做第二个UNNEST - 这是它生成的SQL:

...) WHERE unnest("animal"."categories") = dog::text[]

如果我在PSQL中编写查询,那么UNNEST的结果似乎需要一个子查询:

SELECT categories_element
FROM (
    SELECT UNNEST(animal.categories) as categories_element
) ul
WHERE ul.categories_element like 'Ga%';

有没有办法让Django ORM进行有效的查询?或者我应该放弃ORM并使用原始SQL?

1 个答案:

答案 0 :(得分:1)

您可能有错误的数据库设计。

  

提示:数组不是集合;搜索特定的数组元素即可   数据库错误设计的标志。考虑使用单独的表格   每个项目的行都是一个数组元素。这会更容易   搜索,并可能为大量的更好地扩展   元件。

http://www.postgresql.org/docs/9.1/static/arrays.html