继这个问题之后:Django Postgresql ArrayField aggregation
我有一个类别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?
您可能有错误的数据库设计。
提示: 数组不是集合;搜索特定的数组元素可以是 数据库设计错误的标志。考虑使用单独的表,其中包含 行,表示将成为数组元素的每个项目。这会更容易 进行搜索,并且可能会更好地扩展大量 元素。
http://www.postgresql.org/docs/9.1/static/arrays.html