首页 > 解决方案 > SQLAlchemy 1.4 ORM 中 Query.count 的等价物是什么?

问题描述

给定这样的 SQLAlchemy ORM 模型

class Foo(Base):
    __tablename__ = 'foo'

    id = sa.Column(sa.Integer, primary_key=True)
    name = sa.Column(sa.String())

在 SQLAlchemy 1.4 / 2.0 中,ORM 的session.query习语与 SQLAlchemy 核心select功能*统一,所以要获取所有Foos 我们会做

foos = session.execute(Foo).scalars().all()

代替

foos = session.query(Foo).all()

在当前的 (sqlalchemy<=1.3) ORM 中,我们可以Foo通过这个查询获得数据库中 s 的数量:

nfoos = session.query(Foo).count()

但是我们如何在 SQLALchemy 1.4 中获得计数呢?

session.execute(sa.select(Foo).count())

提高

AttributeError:“选择”对象没有属性“计数”

session.execute(sa.select(Foo)).count()

提高

AttributeError:“ChunkedIteratorResult”对象没有属性“count”

session.execute(sa.select(sa.func.count(Foo)))

提高

sqlalchemy.exc.ArgumentError:需要 SQL 表达式元素,得到<class '__main__.Foo'>

这行得通,

session.execute(sa.select(sa.func.count(Foo.id))).scalars()

但是指定一个属性似乎不如Query.count版本那么 OO / 优雅。此外,它排除了构建查询,但推迟了是否检索计数或模型实例的决定。

count()在新的 SQLAlchemy 1.4 世界中获取 ORM 查询的惯用方法是什么?


* session.query()API 在 1.4 及更高版本中仍然有效

标签: pythonsqlalchemy

解决方案


根据Ilja Everilä的评论,似乎在 SQLAlchemy 1.4 中发布的新 ORM 查询 API中没有直接等效于Query.count的内容(在撰写本文时处于测试阶段)。

等效的功能是调用count(),从子查询中选择*

from sqlalchemy import func, select

count = (
    session.execute(select(func.count()).select_from(select(Foo).subquery()))
    .scalar_one()
)

生成此 SQL

SELECT count(*) AS count_1 
 FROM (SELECT foo.id AS id, foo.name AS name 
         FROM foo) 
AS anon_1

统计一个属性,比如主键列,生成一个简单的SELECT COUNT

count = session.execute(select(func.count(Foo.id))).scalar_one()
SELECT count(foo.id) AS count_1 
FROM foo

Query.count在 1.4 中仍然支持,所以它仍然可以使用,就像 1.3 中可用的所有 ORM 功能一样。


*Query.count 也从子查询中选择而不是SELECT COUNT直接执行。


推荐阅读