0

从这个问题开始:Django Postgresql ArrayField 聚合

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

这样做的“最 Django”方式是什么?

给定一个Animal看起来像这样的模型:

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

然后,根据另一个问题的答案,这适用于查找所有类别,未过滤。

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')

堆栈跟踪的底部是:

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?

4

1 回答 1

1

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

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

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

于 2016-04-20T11:47:24.637 回答