2017-07-18 78 views
1

我试图使用注释值来过滤使用F表达式的查询集,但事实证明它并不像我期望的那样行为。Django聚合和注解行为比较

我想过滤查询集中的对象qs其属性some_prop是该查询集的最大值。例如:

set(qs.values_list('some_prop', flat=True)) 

将输出:

set([1, 3, 5, 7, 9]) 

和我的目标由值9,即最大值过滤qs。我可以很容易地实现,使用聚合:

max_prop = qs.aggregate(max_prop=Max('some_prop'))['max_prop'] 
qs.filter(some_prop=max_prop) 

但我想凝结在一个查询这个行为,所以我用了一个注释,而不是聚集:

qs.annotate(max_prop=Max('some_prop')).filter(some_prop=F('max_prop')) 

然而,这并不表明同样的行为。实际上这只是按照所有some_prop值进行筛选,而不是最大值。

我错过了什么?从注释和聚合功能中必定会有一些误解。

回答

0

由于您的注释并未采用一对多关系中的值,因此相关对象集中的最大值将被注释到与该集相关的对象,因此将采用Max(针对每个对象)只有一个值 - some_prop - 并附加到查询集中的每个对象;这是不直接访问上过滤-some_prop /不同:

当指定一个annotate()子句,在查询集 每个对象将具有指定值注释。

对于单个表格,您需要首先进行聚合以获取最大值,然后过滤该值。

+0

所以我没有办法在'annotate'的单个查询中实现行为。 – dabadaba

+0

@dabadaba有一种解决方法,使用'.values'将所有对象分组为一个并获取最终的最大值:https://stackoverflow.com/questions/9838264/django-record-with-max-element –