2010-12-07 168 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後,在生成的查詢連接的數目變化爲好。