9 Stimmen

Konstruieren Sie den gesamten Baum aus einer SQLAlchemy-Adjazenzlistenbeziehung

Ich habe eine Klasse Node mit einem selbstreferenziellen Mapping 'children' (backref 'parent'), die einen Baum in SQLAlchemy darstellt, und ich möchte den gesamten Baum auswählen. Wenn ich

session.query(Node).all()

dann löst jeder Zugriff auf node.children einen Select aus. Wenn ich einen Join Load mache

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

dann die Sql ausgegeben hat eine unnötige Tabelle Join, da ich den gesamten Baum (alle Knoten) sowieso wollen. Gibt es eine Möglichkeit, dies in SA zu tun, oder sollte ich den Baum einfach selbst außerhalb von SA erstellen?

13voto

Denis Otkidach Punkte 30334

Es gibt kein Problem mit der übergeordneten Eigenschaft, da alle benötigten Informationen bereits in das Objekt geladen sind. SQLAlchemy muss nur nach dem übergeordneten Objekt in der Sitzung suchen und nur dann eine Abfrage stellen, wenn es fehlt. Dies funktioniert jedoch nicht für Child-Objekte: Die Bibliothek kann nicht sicher sein, dass alle Child-Objekte bereits in der Session vorhanden sind. Sie können also den Baum selbst konstruieren und SQLAlchemy anweisen, diese Daten über 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])

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X