2011-04-15 54 views
9

我有一個類Node,帶有一個表示SQLAlchemy中樹的自引用映射'children'(backref'parent'),我想選擇整個樹。如果我做從SQLAlchemy鄰接表關係中構建整個樹

session.query(Node).all() 

然後每次訪問node.children都會觸發select。如果我做加入負載

session.query(Node).options(joinedload_all('children')).all() 

然後發出的sql有一個不必要的表連接,因爲我想整個樹(所有節點)無論如何。有沒有辦法在SA中執行此操作,或者我應該只在SA之外自行構建樹?

回答

12

父屬性沒有問題,因爲所有需要的信息都已經加載到對象中。 SQLAlchemy只需在會話中查找父對象並僅在缺少查詢時發出查詢。但是這對兒童無效:圖書館不能確定所有兒童對象已經在會話中。所以你可以自己構建樹並指示SQLAlchemy使用這個數據通過set_committed_value

from collections import defaultdict 
from sqlalchemy.orm.attributes import set_committed_value 

nodes = session.query(Node).all() 

# Collect parent-child relations 
children = defaultdict(list) 
for node in nodes: 
    if node.parent: 
     children[node.parent.id].append(node) 

# Set collected values 
for node in nodes: 
    set_committed_value(node, 'children', children[node.id]) 
+1

太棒了。我對自己構建樹的猶豫讓節點對象變得模糊,set_committed_value就是我所需要的。謝謝。 – SquaredLoss 2011-04-19 04:11:22