Django ORM:按相关表过滤器的聚合排序

Posted

技术标签:

【中文标题】Django ORM:按相关表过滤器的聚合排序【英文标题】:Django ORM: sort by aggregate of filter of related table 【发布时间】:2012-10-30 11:19:43 【问题描述】:

这是我的模型的一个子集:

class Case(models.Model):
    ... # primary key is named "id"
class Employee(models.Model):
    ... # primary key is named "id"
class Report(models.Model):
    case = ForeignKey(Case, null=True)
    employee = ForeignKey(Employee)
    date = DateField()

给定一个特定的员工,我想生成一份所有案例的列表,按员工最近报告的时间排序。那些没有报告的案例应该排在最后。同一日期的案例(包括 NULL)应按更多标准排序。

我可以在 Django ORM api 中表达这个吗?如果有,怎么做?

在伪 SQL 中,我想我想要

Select Case.*
From Case some-kind-of-join Report
Where report.employee_id = the_given_employee_id
Group by Case.id
Order by Max(Report.date) Desc /* Report-less cases last */, Case.id /* etc. */

我是否需要通过 Report 引入从 Case 到 Employee 的多对多关系才能在 Django ORM 中执行此操作?

【问题讨论】:

你的实际模型是什么样的?你应该可以做类似Case.objects.all().order_by('-date', 'another_field', 'a third field') 我认为 Case.objects.all().order_by('-date') 不会查看 Report.date。我不愿意发布我的模型。 好吧,猜你的模型然后猜对你有帮助的查询是相当困难的。大概您正在使用 ForeignKeys,但除非您至少发布模型的抽象,否则推测没有多大意义 啊,对了,我以为我的 ForeignKey-ing 很明显。我最近的编辑有帮助吗? 【参考方案1】:

django 模型中的每个关系都有a reverse relationship that can be easily queried(包括在您订购时),因此您可以执行以下操作:

Case.objects.all().order_by('-report__date', 'another_field', 'a third field')

但这不会为您提供有关单个特定员工的任何信息。你可以这样做:

Case.objects.filter(report__employee__pk=5).order_by('-report__date', 'another_field', 'a third field')

但这不会返回任何未被您的特定员工编辑的Case 对象。

不幸的是,您不能在本地进行子查询,因此您必须编写自定义注释查询以便执行子查询(即特定员工最后编辑的对象的最后订购日期)。这是未经测试的,但这是一般的想法:

Case \
    .objects \
    .all() \
    .extra(select = 
        "employee_last_edit" : """
            SELECT app_report.date
            FROM app_report
                JOIN app_case ON app_case__id = app_report.case_id
            WHERE app_report.employee_id = %d
        """ % employee.id ) \
    .order_by('-employee_last_edit' , 'something_else')

【讨论】:

如何加入 app_case.id = [来自 Case.objects.all() 的案例 id]?

以上是关于Django ORM:按相关表过滤器的聚合排序的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM按两个相关模型的最大列值过滤

使用多个字段在 MongoDB 聚合框架中按相关性排序

使用多个字段在 MongoDB 聚合框架中按相关性排序

Django ORM数据库查询操作

Django ORM数据库查询操作

Django ORM 查询