0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SQLAlchemy 2.x】`Result`と`ScalarResult`の違いを理解する

0
Posted at

SQLAlchemyで1件取得の処理を書いていたとき、次のエラーに遭遇しました。

AttributeError:
'ScalarResult' object has no attribute
'scalar_one_or_none'

原因は、ResultScalarResultで使えるメソッドを混同していたことでした。

execute()Resultを返す

AsyncSession.execute()を使うと、

result = await session.execute(
    select(User)
)

Resultが返ります。

Resultは基本的にRowを扱う結果オブジェクトです。

ORMモデルを1件だけ取り出したい場合は、

user = result.scalar_one_or_none()

と書けます。

scalar_one_or_none()は、

0件 → None
1件 → Userオブジェクト
複数件 → MultipleResultsFound

という動作になります。

scalars()するとScalarResultになる

一方、

result = await session.scalars(
    select(User)
)

では、返ってくるのはScalarResultです。

ScalarResultは、Rowではなくその中の単一要素を直接扱うための結果オブジェクトです。

そのため1件取得では、

user = result.one_or_none()

と書きます。

ここで、

result.scalar_one_or_none()

とすると、ScalarResultにはそのメソッドがないためエラーになります。

なぜ名前が違うのか?

ResultからORMオブジェクトを取り出すには、まずscalar値へ変換する必要があります。

実際、

result.scalar_one_or_none()

は、SQLAlchemy公式では次と同等の処理として説明されています。

result.scalars().one_or_none()

つまり、

Result
 ↓ scalars()
ScalarResult
 ↓ one_or_none()
User

という流れです。

すでにsession.scalars()を使っている場合は、最初からScalarResultになっているので、もう一度scalarへ変換する必要はありません。

どちらで書けばよい?

ORMモデルを取得するだけなら、

stmt = select(User).where(
    User.id == user_id
)

user = (
    await session.scalars(stmt)
).one_or_none()

と書くとシンプルです。

一方、

result = await session.execute(stmt)

user = result.scalar_one_or_none()

でも同じ目的を実現できます。

まずは次の対応を覚えておくと分かりやすいです。

取得方法 結果 1件または0件
execute() Result scalar_one_or_none()
scalars() ScalarResult one_or_none()

まとめ

  • execute()Resultを返す
  • scalars()ScalarResultを返す
  • Result.scalar_one_or_none()はscalar値を0件または1件取得する
  • ScalarResultではone_or_none()を使う
  • scalar_one_or_none()scalars().one_or_none()と同等

メソッド名だけ暗記するより、今扱っているオブジェクトがResultなのかScalarResultなのかを見ると、エラーの原因を判断しやすくなります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?