注释标签以根据其属于的阈值进行查询

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' 根据解释的原因