2010-12-07 171 views
6

我有一个两表分层安装,其中表A引用表B,然后引用回表A中的不同记录,等等......但只能达到给定的递归深度。如何动态调整SQLAlchemy ORM中的加载深度的递归深度?

我有这个使用SQLAlchemy和声明很好。我也成功地使用了表格关系上的lazyjoin_depth属性的急切加载。这是根据SQLAlchemy documentation

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

我认为与基地ORM对象上的主join_depth财产摆弄,但是这不会工作,因为我有一个多线程的应用程序scoped_session地方,这将是危险的(更不用提的是,该参数在运行时很难在SQLAlchemy中找到!)。

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

我也知道了“WITH RECURSIVE” SQL在一些数据库可以通过CTEs语法,但作为伟大的,因为它是,我想避免的时刻,因为一些数据块仍然不支持它(既不做SQLAlchemy - 至少目前还没有,没有很多方言定制)。

回答

3

有没有官方的方式来做到这一点,但下面的代码为我生成了以下解决方案。我使用链接的docs中的节点示例。

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。这初始值被记录在一个Node.children.property.join_depthjoin_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后,在生成的查询连接的数目变化为好。