我有一个类Node,其自我引用映射'children'(backref'parent')代表SQLAlchemy中的一棵树,我想选择整个树。如果我做
session.query(Node).all()
然后每次访问node.children都会触发一个select。如果我加入了加载
session.query(Node).options(joinedload_all('children')).all()
然后发出的sql有一个不必要的表连接,因为我想要整个树(所有节点)。有没有办法在SA中执行此操作,还是应该在SA外部自己构建树?
答案 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])