2017-05-01 56 views
2

在测试我的Django应用程序时,当使用特定的filter()时,我遇到了特定查询的性能问题。问题解决了,但我不明白为什么。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 

问题是我需要有条件地应用有问题的过滤器,而不是每次。我被过滤器()函数转换为排除()例程这样解决了这个问题:

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

这似乎做的伎俩!

虽然我很高兴,这工作,我不明白两两件事:

1)为什么职位说明过​​滤器()和exclude()似乎表明,它们可以作为平等的,但相反的对待,根据上面的例子,情况并非总是如此。

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

有没有人有任何洞察到这些?

+2

用'print(Finding.objects.filter(...)。query)打印查询'并且全部将被回答 – wim

+0

第二部分(解释问题所在)应该作为答案发布。 – EJoshuaS

回答

2

这两个看起来像filter调用如何在多值关系上工作的预期结果。所述docs详细解释,与实施例:

单个滤波器()调用内部一切被同时施加到匹配所有这些要求 滤出的项目。连续过滤器() 调用进一步限制对象集合,但对于多值关系,它们适用于链接到主模型的任何对象,而不是必须由较早的过滤器() 调用选择的那些对象。

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

+0

谢谢彼得!我已经阅读过那个页面,但它并没有真正点击它,直到你指出它才适用于我的情况。现在回到我的代码并重新评估后续的filter()调用,并可能更改为exclude()。 – rjd