从SQLAlchemy邻接列表关系构造整个树

时间:2011-04-15 17:47:06

标签: sqlalchemy

我有一个类Node,其自我引用映射'children'(backref'parent')代表SQLAlchemy中的一棵树,我想选择整个树。如果我做

session.query(Node).all()

然后每次访问node.children都会触发一个select。如果我加入了加载

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

然后发出的sql有一个不必要的表连接,因为我想要整个树(所有节点)。有没有办法在SA中执行此操作,还是应该在SA外部自己构建树?

1 个答案:

答案 0 :(得分: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])