python - 连接上的过滤器不会传播到相关的 orm.relations

标签 python sqlalchemy

在这里定义一些基本结构:

class A( Base ):

    __tablename__ = 'a'
    id            = Column( types.Integer(), primary_key = True )

    abs           = orm.relation( 'AB', lazy='joined' )

class AB( Base ):

    __tablename__ = 'ab'
    id            = Column( types.Integer(), primary_key = True )
    a_id          = Column( types.Integer(), ForeignKey( 'a.id' ) )
    b_id          = Column( types.Integer(), ForeignKey( 'b.id' ) )

    a             = orm.relation( 'A' )
    b             = orm.relation( 'B', lazy='joined' )

class B( Base ):

    __tablename__ = 'b'
    id            = Column( types.Integer(), primary_key = True )

    bas           = orm.relation( 'AB' )

现在假设我有一个 A 和多个与其相关的 B(例如 A.id = 1),我想基于这些B进行过滤。我执行以下查询:

a = db.session.query( A ).join( A.abs ).filter( AB.b_id = 1, A.id = 1 ).first()

此时,我期望 len( a.abs ) == 1,但事实并非如此。换句话说,应用于连接的过滤器不会传播到 orm.relation。我如何获得这种行为?

最佳答案

The Zen of Eager Loading 中描述了此问题的原因。归结为:您的查询中将有两个不同的联接。一个用于构建要过滤的正确连接(这是您使用 .join(A.abs) 生成的),另一个用于加载关系(ORM 根据 自动插入该关系) >lazy="joined",否则会在访问时查询)。

现在有几种方法可以解决这个问题。但首先你应该考虑一下你真正想要什么。因为当您说A.abs时,您实际上是在说“所有属于该A的AB条目”。但是,当您指定单个 b_id 时,这不是您想要的,因为这不是此关系所代表的意思。所以这是干净的方法:

db.session.query(A, AB).join(A.abs).filter(AB.b_id = 1, A.id = 1)

现在您将获得 AB 作为查询中第二个返回的对象。这是正确的做法,因为在 A.abs 中只有一个 AB 实际上会对 ORM 撒谎:这里不是这样的(而且它可能会破坏东西) 。但是,如果您坚持这样做,这是可能的。您可以使用 sqlalchemy.orm.contains_eager 禁用双连接。 :

db.session.query(A).join(A.abs).options(contains_eager(A.abs)).filter(AB.b_id = 1, A.id = 1)

这将生成一个 A.abs,其中只有一个具有 b_id = 1 的条目。然而,正如已经指出的,这不是一个好的解决方案,也不是您应该做的。

作为额外提示,我建议您在引擎中打开 echo=True 甚至 echo="debug" 以确保您看到正在执行的查询。如果您查看原始查询,则会在同一个表上看到两个联接。

关于python - 连接上的过滤器不会传播到相关的 orm.relations,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18876692/

相关文章:

python - 是否可以将约束 unique = True 除了空字符串设置到 SQLAlchemy 中?

python - sqlalchemy apache mod_wsgi Pyramid 崩溃

python - 在 sqlalchemy 中出现错误 "Trying to redefine primary-key column"

python - 将一组 header 添加到现有数据帧

python - SQLalchemy 1.4.15版本后无法连接到SQL Server

postgresql - 使用 SQLAlchemy 解压 PostGIS/PostgreSQL 记录

python - SQLAlchemy 正确的模型定义和选择/插入

python - tf.extract_image_patches 的实现

python - Pandas groupby - 一组不同的值

python - 使用Python发送短信