注释标签以根据其属于的阈值进行查询
annotate a label to query based on thresholds that it falls within
我正在尝试根据我的查询集的两个属性来标记我的结果,这两个属性属于另一个查询的两个阈值的每个组合。这是一段代码来澄清:
threshold_query = threshold.objects.all()
main_query = main.ojbects.values(
'Athreshold', 'Bthreshold'
).annotate(
Case(
When(
Q(Avalue__lte=threshold_query['Avalue'])
& Q(Bvalue__lte=threshold_query['Bvalue']),
then=Value(threshold_query['label'])
...
)
)
)
阈值模型如下:
class threshold(models.Model):
Avalue = models.FloatField(default=0.1)
Bvalue = models.FloatField(default=0.3)
label = models.CharField(default='Accepted')
所以有一个决定标签的矩阵,例如如果有两个阈值 {'Avalue': 0.4, 'Bvalue': 0.6, 'label': 'rejected' } 和 {'Avalue': 0.7, 'Bvalue': 0.7, 'label': Accepted} 如果你在水平轴上展示 Avalues(命名矩阵的行)和垂直轴上的 Bvalues(命名矩阵的列),这两个阈值的组合决定了单元格的值,即 'Accepted' 或 'Rejected'。 是否可以使用一个查询来获取我的想法? 我的目的是尽量减少由于数据量大而导致的查询数量。
在 Django 1.11+ 上,您可以使用子查询:
from django.db.models import Subquery, OuterRef
Main.objects.annotate(
label=Subquery(
Threshold.objects.filter(
Avalue__gte=OuterRef('Athreshold'),
Bvalue__gte=OuterRef('Bthreshold'),
).values('label')[:1]
)
)
如果值可以匹配多个阈值,则需要在内部查询上定义一些一致的排序。
基于后续问题中的 comment,我最终使用 When 作为传递给 Case 的列表,所以代码类似于:
args = []
for any_threshold in Threshold.objects.all():
label = any_threshold.ThresholdValue
args.append( When(MainAvalue__lte= Avalue,MainBValue__lte= Bvalue,then=Value(label, output_field=CharField()) ))
注释如下:
MainLevel = Case(*args, default=Value('Rejected'))
P.S: 无法使用 'subquery' 根据解释的原因