2017-05-01 58 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