2017-11-11 7 views
0

こんにちは私は、joinloadを使用して私のクエリでフィルタを行いたいと思います。しかし、私はそれを動作させるように見えることはできません。以下は私のサンプルクエリですSQLAlchemy Joinedloadフィルター列

result = (
     session.query(Work). 
     options(
      joinedload(Work.company_users). 
      joinedload(CompanyUser.user) 
     ). 
     filter(Work.id == 1). 
     filter(User.first_name == 'The name'). <<--- I can't get this to work. 
     all() 
    ) 

これを実行すると、私が期待している以上の行が返されます。実際の結果は8rowsのみ返す必要があります。しかし、このクエリを実行すると、私が期待している以上に234行を返します

答えて

1

私はそれを得ました。私がやったのは、joined_eagerへのjoinedloadを置き換えてjoinを追加したのと同じ問題に取り組む人たちのためです。以下改訂コード

1
result = (
    session.query(Work). 
    join(Work.company_users). 
    join(CompanyUser.user). 
    options(
     contains_eager(Work.company_users). 
     contains_eager(CompanyUser.user) 
    ). 
    filter(Work.id == 1). 
    filter(User.first_name == 'The name'). <<--- I can't get this to work. 
    all() 
) 

は、それが動作していない理由は、joinedload(および他のすべての関係のローディング技術は)完全に透明であることを意味していることです。つまり、照会にjoinedloadが含まれていても、関係が満たされる以外の方法では影響を受けません。あなたがで始まる"The Zen of Joined Eager Loading"、次のようになります。参加し熱心な負荷がQuery.join()の使用に多くの類似点を持っていると思われるので

、それは多くの場合、それが使用されなければならないとき、どのようにように混乱を生じさせます。 Query.join()を使用してクエリの結果を変更する際には、joinedload()はクエリの結果を変更しないようにし、レンダリングされた結合の効果を非表示にして関連オブジェクトのみを許可するという点を理解することが重要です存在する。

トリックの1つは、使用できない結合テーブルのエイリアスを使用することです。あなたのクエリは、WorkとUserの間の暗黙的なクロス・ジョイン、したがって余分の行の実行を終了します。だから、結合されたテーブルに対してフィルタリングするために、Query.join()を使用します。それはすでに含まれていることを

session.query(Work).\ 
    join(Work.company_users).\ 
    join(CompanyUser.user).\ 
    filter(Work.id == 1).\ 
    filter(User.first_name == 'The name').\ 
    all() 

を、あなたはまた、代わりにeagerloadsが必要な場合は、クエリを指示することができcontains_eager()と合流:

session.query(Work).\ 
    join(Work.company_users).\ 
    join(CompanyUser.user).\ 
    options(contains_eager(Work.company_users). 
      contains_eager(CompanyUser.user)).\ 
    filter(Work.id == 1).\ 
    filter(User.first_name == 'The name').\ 
    all() 

contains_eager()への連鎖呼び出しに注意してください。