[英]How to use the order_by defined on the relationship in SQLAlchemy and contains_eager?
The Zen of Joined Eager Loading docs recommends using contains_eager()
if we want to keep the relationship order defined in the model. Zen of Joined Eager Loading docs 推荐使用
contains_eager()
如果我们想保持模型中定义的关系顺序。
"If we wanted to use just one JOIN for collection loading as well as ordering, we use the contains_eager() option, described in Routing Explicit Joins/Statements into Eagerly Loaded Collections below." “如果我们只想使用一个 JOIN 进行集合加载和排序,我们可以使用 contains_eager() 选项,如下文将显式连接/语句路由到 Eagerly Loaded 集合中所述。”
But the following example seems to behave otherwise.但下面的例子似乎表现得不一样。 I must be missing something, but unsure what.
我一定错过了什么,但不确定是什么。
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")
Generates the following SQL:生成以下 SQL:
SELECT parent.parent_id, parent.name,
child.order, child.name,
FROM parent, child
WHERE parent.parent_id = 99 AND parent.name = 'foo'
For some reason,因为某些原因,
ORDER BY child.order
is missing, even though it's defined in the relationship()
.丢失了,即使它是在
relationship()
定义的。 Any hints?任何提示?
It works fine if the order_by is specified at query time, but I want to avoid writing the same ordering criteria multiple times.如果在查询时指定 order_by,它工作正常,但我想避免多次编写相同的排序条件。
The documentation is correct, and it refers to the fact that if using most out-of-the box eager loading methods, the query is modified and might not be optimal.文档是正确的,它指的是如果使用大多数开箱即用的急切加载方法,查询会被修改并且可能不是最佳的。
The suggestion is then to use contains_eager
where:然后建议使用
contains_eager
,其中:
1) the user is responsible for constructing the correct query (including joins, filters, ordering etc) 1) 用户负责构造正确的查询(包括连接、过滤器、排序等)
2) by using contains_eager
the user hints SA that the specified relationship is included in the query. 2) 通过使用
contains_eager
用户提示SA 指定的关系包含在查询中。
The way to load relationship eagerly would be to use joinedload
:急切加载关系的方法是使用
joinedload
:
q_joined = (
session
.query(Parent)
.options(joinedload(Parent.children))
.filter(Parent.parent_id == parent_id)
)
But you cannot apply these additional filters in this case.但是在这种情况下您不能应用这些附加过滤器。
Using the contains_eager
you would do:使用
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
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.