状況に応じてさまざまなフィールドに基づいてフィルター処理したい一般的なクエリセットをキャッシュしました。そもそもキャッシュする利点を失った場合、評価されたクエリセットをフィルタリングすることによって、私は疑問に思っています。Django は、キャッシュされたクエリセットと後で適用するフィルターの作成に関与するクエリセットの集合体である別のクエリセットをゼロから作成するだけですか?
1 に答える
はい、結果は破棄されます。
これは、ソースから見ることができます:をfilter()
呼び出し_filter_or_exclude()
、_clone()
そのクエリに追加します。_clone
、ご覧のとおり、_result_cache
属性を設定していません。
一般に、共通の結果を維持するために何ができるかは明確ではありません。結果セットが小さい複雑なクエリの場合は、主キーが見つかった結果の 1 つであることを確認する SQL を発行するだけで置き換えることができますが、それが常により効率的であるとは限りません。セマンティクスを混乱させる可能性があります(DBがキャッシュされてから追加のフィルターを実行するまでの時間にクエリ結果に影響を与える方法で変更された場合)。
ID を手動で保存するこの動作を強制する場合は、次のようにします。
pks = SomeObject.objects.filter(...).values_list('pk', flat=True)
some_of_them = SomeObject.objects.filter(pk_in=pks).filter(...)
others = SomeObject.objects.filter(pk_in=pks).filter(...)
もちろん、Python でフィルタリングを行うこともできます。
common = SomeObject.objects.filter(...)
some_of_them = [m for m in common if m.attribute == 'foo']
others = [m for m in common if m.other_attribute == 'bar']
(必要に応じて使用するか、 in の定義をラップしてより明示的にすることもできますfilter(lambda m: m.attribute == 'foo', common)
。)common
list
これらのいずれかまたはクエリを再発行するかどうかは、関連するセットのサイズ、フィルターの複雑さ、および存在するインデックスに大きく依存します。