从这个问题继:Django Postgresql ArrayField aggregationDjango的Postgres的ArrayField聚合和过滤
我有分类的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')
堆栈跟踪的底部是:
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?
也许可以使用https://docs.djangoproject.com/en/1.9/ref/models/querysets/#extra得到子查询在那里。 'annotate'似乎有些错误(通常用于聚合类型函数) – Anentropic
Thanks @Antropic - 我确实看过'extra',但看不到添加子查询的方法。下面的答案可能是“最真实”的 - 模式并不适合真正的目的。我已经实现了一个迷你查询构建器,可以从ArrayFields中进行选择和排序,并且看起来很好地工作。 – jamesc
我想知道你是否可以把子查询放在'tables'参数中 – Anentropic