1

私は subqueryload/subqueryload_all をかなり頻繁に使用しており、サブクエリロード中に使用されるクエリを非常に明示的に定義する必要があるエッジケースに遭遇しました。たとえば、投稿とコメントがある状況があります。私のクエリは次のようになります。

posts_q = db.query(Post).options(subqueryload(Post.comments))

ご覧のとおり、各投稿のコメントを読み込んでいます。問題は、すべての投稿のコメントが必要ないことです。削除されたフィールドも考慮する必要があり、作成時間の降順で並べ替える必要があります。これが行われていることを私が観察した唯一の方法は、relationship()投稿とコメントの間の宣言にオプションを追加することです。私はこれをしないことを好みます.b / cは、アプリ内にこれらの制約が適用されない可能性のある他の場所があるため、その関係をその後どこでも再利用できないことを意味します.

私がやりたいのは、投稿のコメントを読み込むために subqueryload/subqueryload_all が使用するクエリを明示的に定義することです。DisjointedEagerLoading hereについて読みましたが、基本クエリを受け取る特別な関数と、指定された関係をロードするクエリを定義するだけでよいようです。これは、この状況に適した方法ですか? 以前にこのエッジケースに遭遇したことのある人はいますか?

4

2 に答える 2

2

Post答えは、との間に複数の関係を定義できるということですComment

class Post(...):
    active_comments = relationship(Comment,
         primary_join=and_(Comment.post_id==Post.post_id, Comment.deleted=False),
         order_by=Comment.created.desc())

次に、その関係によってサブクエリロードできるはずです。

posts_q = db.query(Post).options(subqueryload(Post.active_comments))

既存の.comments関係を別の場所で引き続き使用できます。

于 2013-10-01T12:29:43.500 に答える
1

私もこの問題を抱えていましたが、これが設計上の問題であることに気付くまでに少し時間がかかりました。あなたが言うときPost.commentsは、「これらはその投稿のすべてのコメントです」という関係を指します。ただし、今はそれらをフィルタリングする必要があります。その条件をどこかに指定すると、subqueryload本質的に値のサブセットのみを にロードすることになりますPost.comments。したがって、欠落している値があります。基本的に、モデル内のデータの表現に誤りがあります。

ここでの問題は、明らかにこの値がどこかに必要であるため、これにどのようにアプローチするかです。私が行く方法は、自分でサブクエリを作成し、そこで特別な条件を指定することです。つまり、投稿のリストとコメントのリストという 2 つのオブジェクトが返されます。これはきれいな解決策ではありませんが、少なくともデータが間違った方法で表示されているわけではありません。Post.commentsなんらかの理由でアクセスした場合は、すべての投稿が含まれていると考えて問題ありません。

ただし、改善の余地があります。これをクラスにアタッチして、2 つの変数を持ち歩かないようにすることもできます。簡単な方法は、published_comments追加のパラメーターを指定するなど、2 番目の関係を定義することです。次に、属性 events などを使用して、誰も書き込まないように制御することもできます。これらのイベントでは、操作を禁止する代わりに、操作を許可する方法を処理できます。唯一の問題は、更新が発生したときです。たとえば、コメントを追加したときに、お互いを認識していないため、自動的に更新されませんPost.commentspublished_comments繰り返しますが、これが必要な機能である場合は、このためのイベントを取得します (ただし、上記の醜いソリューションでは、それもありません)。

最後のハイブリッド ソリューションとして、最初のアプローチを取り、それらの値をオブジェクトに割り当てることができますPost.deleted_comments = deleted_comments

ここで心に留めておくべきことは、ORM が作成するクエリを操作することは、後で問題を引き起こす可能性があるため、一般的に賢明な考えではないということです。私はこのアプローチを採用し、クエリを操作しました (contains_eagerこれは簡単に可能です) が、いくつかの点で問題が発生したため (通常は機能します)、そのアプローチをやめました。

于 2013-10-01T12:17:37.950 に答える