如何在SQLAlchemy ORM中动态调整急加载的递归深度?

8
我有一个两个表的分层设置,其中表A引用表B,然后再引用回不同的记录在表A中,以此类推......但仅限于给定的递归深度。
我使用SQLAlchemy和declarative使其正常工作。我还成功地使用了懒加载,其中包括表关系上的lazy和join_depth属性。这是根据SQLAlchemy documentation
然而,这种安排在程序加载时将递归深度固定为'join_depth'...但是,对于我正在使用的数据,我知道每次应该使用递归深度。如何在每个查询基础上更改使用的递归深度?
我考虑过在基本ORM对象上调整主要的join_depth属性,但这行不通,因为我有一个多线程的scoped_session应用程序,那样做很危险(更不用说在运行时在SQLAlchemy中定位该参数非常困难!)。
我也尝试使用查询中的joinedload,但是不知道如何改变其深度。
我也知道一些数据库支持的'WITH RECURSIVE' SQL语法,可以通过CTEs实现,但是由于某些数据库仍不支持它(SQLAlchemy目前也不支持它,至少没有经过很多方言定制),所以我想暂时避免使用它。
1个回答

7

目前没有官方的解决方法,但是根据代码,我找到了以下解决方案。我使用了你链接的文档中提供的Node示例。

class Node(Base):
    __tablename__ = 'node'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('node.id'))
    data = Column(String(50))
    children = relationship("Node",
                    lazy="joined",
                    join_depth=2)

在创建时,children 属性被赋予了 2 的 join_depth 值。这个初始值被记录在 Node.children.property.join_depth 中。然而,改变这个值不会起作用。在初始化时,关系创建了一个“策略”来连接,这个策略复制了 join_depth 的值。要改变关系策略的连接深度,你需要设置 Node.children.property.strategy.join_depth

>>> engine.echo = True  # print generated queries
>>> session.query(Node).all()  # with default join_depth
SELECT node.id AS node_id, node.parent_id AS node_parent_id, node.data AS node_data, node_1.id AS node_1_id, node_1.parent_id AS node_1_parent_id, node_1.data AS node_1_data, node_2.id AS node_2_id, node_2.parent_id AS node_2_parent_id, node_2.data AS node_2_data FROM node LEFT OUTER JOIN node AS node_2 ON node.id = node_2.parent_id LEFT OUTER JOIN node AS node_1 ON node_2.id = node_1.parent_id
>>> Node.children.property.strategy.join_depth = 4  # new join depth
>>> session.query(Node).all()  # with new join depth
SELECT node.id AS node_id, node.parent_id AS node_parent_id, node.data AS node_data, node_1.id AS node_1_id, node_1.parent_id AS node_1_parent_id, node_1.data AS node_1_data, node_2.id AS node_2_id, node_2.parent_id AS node_2_parent_id, node_2.data AS node_2_data, node_3.id AS node_3_id, node_3.parent_id AS node_3_parent_id, node_3.data AS node_3_data, node_4.id AS node_4_id, node_4.parent_id AS node_4_parent_id, node_4.data AS node_4_data FROM node LEFT OUTER JOIN node AS node_4 ON node.id = node_4.parent_id LEFT OUTER JOIN node AS node_3 ON node_4.id = node_3.parent_id LEFT OUTER JOIN node AS node_2 ON node_3.id = node_2.parent_id LEFT OUTER JOIN node AS node_1 ON node_2.id = node_1.parent_id

在设置Node.children.property.strategy.join_depth之后,生成的查询中连接数量也会随之改变。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接