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

Squ*_*oss 9 python sqlalchemy

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

session.query(Node).all()
Run Code Online (Sandbox Code Playgroud)

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

session.query(Node).options(joinedload_all('children')).all()
Run Code Online (Sandbox Code Playgroud)

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

Den*_*ach 13

父属性没有问题,因为所需的所有信息都已加载到对象中.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])
Run Code Online (Sandbox Code Playgroud)