【问题标题】:Return multiple values in Subquery in Django ORM在 Django ORM 的子查询中返回多个值
【发布时间】:2020-11-11 04:21:24
【问题描述】:

问题是关于 Django ORM 中的 SubqueryArrayAgg

例如,我有 2 个模型彼此之间没有任何关系:


class Example1(models.Model):
    ident = Integerfield()

class Example2(models.Model):
    ident = IntegerField()
    email = EmailField()

FK、M2M、O2O 2 种模型之间没有联系,但是字段 ident 在两个模型中可能是相同的整数(这在某种程度上是一个连接),并且通常对于 Example1 的 1 个实例,Example2 的多个实例具有相同的 ident

我想创建一个subqueryarrayagg (db Postgres) 或 RAWSQL 之外的任何方式来进行这样的注释:

Example1.objects.annotate(
cls2=Subquery(
Example2.objects.filter(
ident=OuterRef(‘ident’
).values_list(‘email’, flat=True).

#or

Example1.objects.annotate(
cls2=StringAgg(
something here???, 
delimeter=’, ‘,
 distinct=True,)

确定这不起作用,因为Subquery 返回多行,并且似乎不可能使用StringAgg,因为我们在模型之间没有任何连接(没有任何东西可以放在StringAgg 中)。

任何想法如何在一个查询集中使用来自Example2 的电子邮件注释Example1

这将用于 CASE 表达式。

谢谢...

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    对于MySQL后端,你可以使用django-mysql的GroupConcat,或者看the post自己做一个聚合函数:

    from django_mysql.models import GroupConcat
    Example1.objects.annotate(
        cls2=Subquery(
            Example2.objects.filter(ident=OuterRef('ident')).values('ident')\
            .annotate(emails=GroupConcat('email')).values('emails')
        )
    )
    

    对于 PostgreSQL 后端,你可以使用ArrayAgg or StringAgg:

    from django.contrib.postgres.aggregates import ArrayAgg, StringAgg
    Example1.objects.annotate(
        cls2=Subquery(
            Example2.objects.filter(ident=OuterRef('ident')).values('ident')\
            .annotate(emails=ArrayAgg('email')).values('emails')
        )
    )
    # or
    Example1.objects.annotate(
        cls2=Subquery(
            Example2.objects.filter(ident=OuterRef('ident')).values('ident')\
            .annotate(emails=StringAgg('email', ',')).values('emails')
        )
    )
    

    【讨论】:

    • 它有效。很好的答案,非常感谢,虽然我不完全理解第一个值('ident')背后的逻辑。
    • 表示按 ident 字段分组。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多