sqlalchemy:关闭声明性多态连接?
sqlalchemy 有没有办法在单个查询中关闭声明式的多态连接加载?大多数时候这很好,但我有:
class A(Base) :
discriminator = Column('type', mysql.INTEGER(1), index=True, nullable=False)
__mapper_args__ = { 'polymorphic_on' : discriminator }
id = Column(Integer, primary_key=True)
p = Column(Integer)
class B(A) :
__mapper_args__ = { 'polymorphic_identity' : 0 }
id = Column(Integer, primary_key=True)
x = Column(Integer)
class C(A) :
__mapper_args__ = { 'polymorphic_identity' : 1 }
id = Column(Integer, primary_key=True)
y = Column(String)
我想进行一个查询,以便获得 Bx > 的所有 A.ids。 10,如果 A 实际上是 B,或者 Cy == 'blah',如果 A 实际上是 C,则全部按 p 排序。
为了迭代地做到这一点,我从第一部分开始 - “如果 A 实际上是 B,则获取 Bx > 10 的所有 A.id”。所以我想我应该从外部连接开始:
session.query(A.id).outerjoin((B, B.id == A.id)).filter(B.x > 10)
...除了似乎没有办法避免让outerjoin((B, B.id == A.id))子句生成A中所有内容的完整连接子选择中 B 中的所有内容。如果 B 不继承自 A,那么这种情况就不会发生,所以我认为是多态声明性代码生成做到了这一点。有办法把它关掉吗?或者强制外连接做我想做的事?
我想要的是这样的:
select a.id from A a left outer join B b on b.id == a.id where b.x > 10
但我得到的是这样的:
select a.id from A a left outer join (select B.id, B.x, A.id from B inner join A on B.id == A.id)
...顺便说一句,如果不可能,那么后者的效率是否比前者低? SQL 引擎实际上会执行该内连接,还是会忽略它?
Is there a way in sqlalchemy to turn off declarative's polymorphic join loading, in a single query? Most of the time it's nice, but I have:
class A(Base) :
discriminator = Column('type', mysql.INTEGER(1), index=True, nullable=False)
__mapper_args__ = { 'polymorphic_on' : discriminator }
id = Column(Integer, primary_key=True)
p = Column(Integer)
class B(A) :
__mapper_args__ = { 'polymorphic_identity' : 0 }
id = Column(Integer, primary_key=True)
x = Column(Integer)
class C(A) :
__mapper_args__ = { 'polymorphic_identity' : 1 }
id = Column(Integer, primary_key=True)
y = Column(String)
I want to make a query such that I get all A.ids for which B.x > 10, if that A is actually a B, or where C.y == 'blah', if that A is actually a C, all ordered by p.
To do it iteratively, I'm starting just with the first part - "get all A.id for which B.x > 10 if that A is actually a B". So I thought I would start with an outer join:
session.query(A.id).outerjoin((B, B.id == A.id)).filter(B.x > 10)
... except there seems to be no way to avoid having that outerjoin((B, B.id == A.id)) clause generate a full join of everything in A to everything in B within a subselect. If B doesn't inherit from A, then that doesn't happen, so I'm thinking it's the polymorphic declarative code generation that does that. Is there a way to turn that off? Or to force the outerjoin to do what I want?
What I want is something like this:
select a.id from A a left outer join B b on b.id == a.id where b.x > 10
but instead I get something like:
select a.id from A a left outer join (select B.id, B.x, A.id from B inner join A on B.id == A.id)
... as an aside, if it's not possible, then is the latter less efficient than the former? Will the sql engine actually perform that inner join, or will it elide it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试单独为每个子类构建查询,然后将它们联合在一起。查询
B.id
时,SQLAlchemy 隐式加入超类并返回A.id
,因此采用B.id
的选择并集C.id
仅返回单个列。您仍然会得到一个子选择,但只有一个连接“层” - 外部选择只是重命名列。
You could try building the queries for each subclass individually, then unioning them together. When querying
B.id
, SQLAlchemy implicitly joins the superclass and returnsA.id
instead, so taking the union of selects forB.id
andC.id
only returns a single column.You still get a subselect, but only a single "layer" of joins - the outer select is just renaming the column.
您应该使用 with_polymorphic()而不是outerjoin(),它似乎返回了预期的结果:
相比:
我用来测试这个的代码,以防有人想测试这个简洁的SQLAlchemy:
我在Python 2.7上用SQLAlchemy 0.6.4运行了这个。
You should use with_polymorphic() instead of outerjoin(), which seems to return the expected results:
Compared to:
The code I used to test this, in case anybody wants to test this neat bit of SQLAlchemy:
I ran this on Python 2.7 with SQLAlchemy 0.6.4.