在测试我的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()会导致结果大幅跳跃。
有没有人对这些中的任何一个有任何见解?
答案 0 :(得分:2)
这两个看起来都是连续filter
调用如何处理多值关系的预期结果。 docs详细解释,例如:
单个filter()调用中的所有内容同时应用于 过滤掉符合所有要求的项目。连续过滤器() 调用进一步限制了对象集,但对于多值 关系,它们适用于链接到主要模型的任何对象,而不是 必然是那些由早期过滤器选择的对象() 调用
因此,您的第二次filter
调用会返回任何Finding
,其中至少有一个非错误结果。 exclude
调用会返回任何不存在至少一个错误结果的发现。在单个值上查询不可为空的字段时,它们是可互换的,但并非在所有情况下都可以。