SQLAlchemyが揺れる!

今日、彼は自分のブログのモデルに携わり、エントリーにコメントカウンターを付けることにしました(これはブログエントリーです)。 アプリケーションのデータ表現はSQLAlchemyを使用して実装されます。これは、データソースレイヤーの現在の(主にDjangoとRailsによる) Active Record実装とは異なり、これがデータマッパー実装であることを思い出します。



コメントを数えるために、entries_tableにバッテリーがないため、毎回コメントを数える必要があります。 しかし、それを正しく行う方法は?







オンデマンドでダウンロード





最初に思い浮かぶのは、Entry.comments_count属性をオンデマンドでダウンロード可能(遅延読み込み属性)にし、リクエストを切断することです:



SELECT COUNT(*) FROM comments_table WHERE comments_table.entry_id == <ENTRY_ID>









それは簡単です、属性に頼る-要求が発生し、適用しない-それはしません。 しかし、たとえば、ブログのメインページでどのようにアピールが行われたか(各エントリのコメントの数が示されている)など、アピールがあまりにも頻繁に発生した場合はどうでしょう。 これには、n + 1クエリが必要になります。nはページごとのレコード数です。 あまり良くない...



テーブルを結合する





そして今、最も興味深いのは、SQLAlchemyがクラスを個々のテーブルだけでなく、JOINやSELECTにもマップできることです。 つまり、必要なのはSQLクエリを作成することだけです。



SELECT < entries_table>, COUNT(comments_table.id)

FROM entries_table

LEFT OUTER JOIN comments_table

ON entries_table.id == comments_table.entry_id

GROUP BY entries_table.id









SQLAlchemy メタデータマッピングの説明を使用すると、次のようになります。



entries_with_comments = select(

[

entries_table,

func.count(comments_table.c.id).label("comments_count")

],

from_obj=[entries_table.outerjoin(comments_table)],

group_by=[c for c in entries_table.c]

).alias("entries_with_comments")









とても簡単です。 次に、古典的なエントリをこのSELECTにマップします::



mapper(Entry, schema.entries_with_comments,

primary_key=[schema.entries_with_comments.c.id],

)









すべて準備完了です! エントリエントリを取得すると、各インスタンスにcomments_count属性が設定されます。 そして、これらすべてを1つのリクエストで。



ActiveRecordを使用したDjango.ormとRailsは神経質になります;)。



All Articles