如何在加入之前限制具有 n 到 n 关系的表中的记录,以避免在 django ORM 中重复?
How to limit records in tables with n to n relation before joining them , to avoid duplicates in django ORM?
扩展我之前的 。我有四个 tables:
A <--- Relation ---> B ---> Category
(所以A和B之间的关系是n对n,其中B和Category之间的关系是n对1)
关系在 B 中存储 A 的 'Intensity'。我需要计算 A 在每个类别中的强度并找到最大值结果。可以使用:
A.objects.values(
'id', 'Relation_set__B__Category_id'
).annotate(
AcIntensity=Sum(F('Relation_set__Intensity'))
).aggregate(
Max(F('AcIntensity'))
)['AcIntensity__max']
现在我需要预先根据 B 中的某些字段过滤强度:
A.objects.values(
'id', 'Relation_set__B__Category_id'
).filter(
Relation_set__B__BType=type_filter
).annotate(
AcIntensity=Sum(F('Relation_set__Intensity'))
).aggregate(
Max(F('AcIntensity'))
)['AcIntensity__max']
但是我需要避免由于 table join 导致的重复导致计算混乱。(除了那些定义过滤的字段,我不需要 B 中的任何字段)
有没有办法使用 Django ORM 实现此目的?
更新
我认为我需要的是在查询数据库之前限制 Relation table 中的记录(基于 B 过滤器)。我该怎么做?
(也许使用 Prefetch_related 和预取?)
我终于用 conditional aggregation 完成了。
您可以在 中找到更多详细信息。
所以最终代码将是:
result = A.objects.values(
'id', 'Relation_set__B__Category_id'
).annotate(
AcIntensity=Sum(
Case(
When(
q_statement_for_filter,then=F('Relation_set__Intensity'),
),
default=0,
output_field=FloatField()
)
)
).exclude(
AcIntensity=0
).aggregate(
Max(F('AcIntensity'))
)['AcIntensity__max']
注意 'q_statement_for_filter' 不能为空 Q()。
扩展我之前的
A <--- Relation ---> B ---> Category
(所以A和B之间的关系是n对n,其中B和Category之间的关系是n对1) 关系在 B 中存储 A 的 'Intensity'。我需要计算 A 在每个类别中的强度并找到最大值结果。可以使用:
A.objects.values(
'id', 'Relation_set__B__Category_id'
).annotate(
AcIntensity=Sum(F('Relation_set__Intensity'))
).aggregate(
Max(F('AcIntensity'))
)['AcIntensity__max']
现在我需要预先根据 B 中的某些字段过滤强度:
A.objects.values(
'id', 'Relation_set__B__Category_id'
).filter(
Relation_set__B__BType=type_filter
).annotate(
AcIntensity=Sum(F('Relation_set__Intensity'))
).aggregate(
Max(F('AcIntensity'))
)['AcIntensity__max']
但是我需要避免由于 table join 导致的重复导致计算混乱。(除了那些定义过滤的字段,我不需要 B 中的任何字段)
有没有办法使用 Django ORM 实现此目的?
更新
我认为我需要的是在查询数据库之前限制 Relation table 中的记录(基于 B 过滤器)。我该怎么做?
(也许使用 Prefetch_related 和预取?)
我终于用 conditional aggregation 完成了。
您可以在
result = A.objects.values(
'id', 'Relation_set__B__Category_id'
).annotate(
AcIntensity=Sum(
Case(
When(
q_statement_for_filter,then=F('Relation_set__Intensity'),
),
default=0,
output_field=FloatField()
)
)
).exclude(
AcIntensity=0
).aggregate(
Max(F('AcIntensity'))
)['AcIntensity__max']
注意 'q_statement_for_filter' 不能为空 Q()。