是否可以从不同的Case
指令中收集结果并将其存储在数组字段中?
要测试的几个要点:
banana = Fruit.objects.create(name='banana', type='tropicals', country_of_import='Africa')
orange = Fruit.objects.create(name='orange', type='citrus', country_of_import='Spain')
apple = Fruit.objects.create(name='apple', type='apples', country_of_import='Russia')
这里是经理,需要收集所有案件结果。 ToArray
作为完成这项工作的可能功能。根据{{3}},有一个具有相似名称ArrayAgg
的函数:
返回连接到数组中的值列表,包括空值。
它仅适用于一个表达式,但不适用于多个表达式:
class CustomManager(Manager):
def get_queryset(self):
query = super().get_queryset().annotate(
additional_info=ToArray(
Case(
When(
type='tropicals',
then=Value('This fruit is tropical...')
),
output_field=CharField()
),
Case(
When(
country_of_import='Spain',
then=Value('This fruits was grown in Spain'),
),
output_field=CharField()
)
)
)
return query
最终结果将是:
banana.additional_info = ['This fruit is tropical.']
orange.additional_info = ['This fruits was grown in Spain.']
是否可以使用现有功能处理?还是需要自己编写?
答案 0 :(得分:0)
实际上,没有明显的方法可以实现此目的。最简单的解决方案是像这样使用CombinedExpression
类:
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Manager, Case, When, Value, CharField
from django.db.models.expressions import CombinedExpression
class FruitManager(Manager):
def get_queryset(self):
query = super().get_queryset()
query = query.annotate(
result=(
CombinedExpression(
ArrayAgg(Case(
When(
type='tropicals',
then=Value('This fruit is tropical...'),
),
output_field=CharField()
)),
'||'
,
ArrayAgg(Case(
When(
country_of_import='Africa',
then=Value('This fruit is citrus...'),
),
output_field=CharField(),
default=Value('default value')),
),
)
)
)
return query
它将被编译为以下SQL:
SELECT "core_fruit"."id",
(
ARRAY_AGG(CASE
WHEN "core_fruit"."type" = 'tropicals'
THEN 'This fruit is tropical...'
ELSE NULL END) ||
ARRAY_AGG(
CASE
WHEN "core_fruit"."country_of_import" = 'Africa'
THEN 'This fruit is citrus...'
ELSE 'default value' END
)
) AS "result"
FROM "core_fruit"
GROUP BY "core_fruit"."id";
但是有一点需要注意,CombinedExpression
没有记录,因为仅用于内部使用。