如何使用在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?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQLAlchemy 中组合两个模型类

如何使用 sqlalchemy 关系实现多个连接

如何使用 SQLAlchemy 插入数据

SQLAlchemy 在包含的循环中生成查询

Flask 如何使用 SQLAlchemy 框架

如何使用 sqlalchemy 查询 jsonb 数组