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

Rus*_*uss 7 python sqlalchemy recursive-query adjacency-list

我有一个两表分层设置,其中表A引用表B,然后引用表A中的不同记录,依此类推......但仅限于给定的递归深度.

我使用SQLAlchemy和声明性工作得很好.我也成功地使用表格关系lazyjoin_depth属性的热切加载.这是根据SQLAlchemy文档.

但是,这种安排将递归深度固定在' join_depth'程序加载时间一次......但是对于我正在使用的数据,我知道每次应该使用的递归深度. 如何更改基于每个查询的递归深度?

我考虑过摆弄join_depth基础ORM对象上的master 属性,但这不起作用,因为我有一个多线程的scoped_session应用程序,这将是危险的(更不用说参数很难到在运行时位于SQLAlchemy内!).

我也看过使用joinedload查询,但没有看到如何改变深度.

我也知道WITH RECURSIVE通过CTE在一些数据库中提供的' 'SQL语法,但是尽管如此,我想暂时避免这种情况,因为一些数据库仍然不支持它(SQLAlchemy也没有 - 至少不是现在而且没有很多方言定制).

dav*_*ism 6

没有正式的方法可以做到这一点,但遵循代码为我提供了以下解决方案.我正在使用您链接的文档中的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)
Run Code Online (Sandbox Code Playgroud)

在创建时,该children属性的a join_depth为2.该初始值记录在Node.children.property.join_depth.但是,更改此值将不起作用.在init,该关系为加入创建了一个"策略",并且复制了该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
Run Code Online (Sandbox Code Playgroud)

设置后Node.children.property.strategy.join_depth,生成的查询中的联接数也会更改.