如何使用在SQLAlchemy和contains_eager中的关系上定义的order_by?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用在SQLAlchemy和contains_eager中的关系上定义的order_by?相关的知识,希望对你有一定的参考价值。
Zen of Joined Eager Loading文档建议使用contains_eager()
,如果我们要保持模型中定义的关系顺序。
“如果我们只想使用一个JOIN进行集合加载和排序,我们将使用contains_eager()选项,如下面的将显式联接/语句路由到渴望加载的集合中所述。”
但是以下示例似乎有其他行为。我肯定想念什么,但不确定。
class Parent(Base):
__tablename__ = "parent"
parent_id = Column(types.Integer, primary_key=True)
name = Column(types.String(200), nullable=False)
class Child(Base):
__tablename__ = "child"
order = Column(types.Integer, default=0)
name = Column(types.String(200))
parent_id = Column(types.Integer, ForeignKey(Parent.parent_id))
parent = relationship(
Parent,
backref=backref(
"children",
cascade="all,delete",
order_by="Child.order",
),
)
query = session.query(Parent).options(
contains_eager(Parent.children)
).filter(Parent.parent_id == 99).filter(Child.name == "foo")
生成以下SQL:
SELECT parent.parent_id, parent.name,
child.order, child.name,
FROM parent, child
WHERE parent.parent_id = 99 AND parent.name = 'foo'
由于某种原因,
ORDER BY child.order
丢失,即使它在relationship()
中定义。有任何提示吗?
如果在查询时指定了order_by,效果很好,但我想避免多次编写相同的排序条件。
答案
该文档是正确的,它涉及以下事实:如果使用大多数现成的急切加载方法,则查询将被修改,并且可能不是最佳选择。
然后建议使用contains_eager
,其中:
1)用户负责构建正确的查询(包括联接,过滤器,排序等)
2)通过使用contains_eager
用户提示 SA在查询中指定的关系为包括。
热切加载关系的方法是使用joinedload
:
q_joined = (
session
.query(Parent)
.options(joinedload(Parent.children))
.filter(Parent.parent_id == parent_id)
)
但是在这种情况下,您不能应用这些其他过滤器。
使用contains_eager
,您会做:
q_manual = (
session
.query(Parent)
.join(Child) # MUST HAVE THIS
.options(contains_eager(Parent.children))
.filter(Parent.parent_id == 99)
# .filter(Child.name == "foo") # you can add this, but you are "tricking" SA into believing that only these 'Child' are part of the Parent.children relationship.
.order_by(Parent.parent_id, Child.order) # JUST ADD THIS to solve the ordering
)
以上是关于如何使用在SQLAlchemy和contains_eager中的关系上定义的order_by?的主要内容,如果未能解决你的问题,请参考以下文章