Django filter()增加结果QuerySet而不是减少

时间:2017-05-01 18:46:06

标签: python django

在测试我的Django应用程序时,当使用特定的filter()时,我遇到了特定查询的性能问题。这个问题已经解决了,但我不明白为什么。

我根据3条标准过滤QuerySet。当同时包含它们时,我得到预期的结果数。当将其中一个子句移动到它自己的filter()调用时,生成的QuerySet比应该的大得多,并且看起来像是重复的条目。

请参阅下文以了解此情况。将result__is_false=False子句移动到其自己的filter()会导致生成的QuerySet中出现大量扩展。

>>> Finding.objects.filter(project=1, result__scan_session__is_enabled=True,\ 
    result__is_false=False).count()
3566

>>> Finding.objects.filter(project=1, result__scan_session__is_enabled=True)\
    .filter(result__is_false=False).count()
10050380

问题是我需要有条件地应用有问题的过滤器,而不是每次都有。我通过将filter()例程转换为exclude()例程来解决问题,如下所示:

>>> Finding.objects.filter(project=1, result__scan_session__is_enabled=True)\
    .exclude(result__is_false=True).count()
3566

这似乎已经成功了!

虽然我很高兴这有效,但我不理解两件事:

1)为什么解释filter()和exclude()的帖子似乎表明它们可以被视为相等但相反,当基于上面的例子时,情况并非总是如此。

2)为什么将result__is_false=False子句移动到自己的filter()会导致结果大幅跳跃。

有没有人对这些中的任何一个有任何见解?

1 个答案:

答案 0 :(得分:2)

这两个看起来都是连续filter调用如何处理多值关系的预期结果。 docs详细解释,例如:

  

单个filter()调用中的所有内容同时应用于   过滤掉符合所有要求的项目。连续过滤器()   调用进一步限制了对象集,但对于多值   关系,它们适用于链接到主要模型的任何对象,而不是   必然是那些由早期过滤器选择的对象()   调用

因此,您的第二次filter调用会返回任何Finding,其中至少有一个非错误结果。 exclude调用会返回任何不存在至少一个错误结果的发现。在单个值上查询不可为空的字段时,它们是可互换的,但并非在所有情况下都可以。