2010-12-07 6 views
6

Ich habe eine hierarchische Zwei-Tabellen-Konfiguration, wobei Tabelle A Tabelle B referenziert, die dann auf einen anderen Datensatz in Tabelle A verweist, und so weiter ... aber nur bis zu einer bestimmten Rekursionstiefe.Wie passt man die Rekursionstiefe für das eifrige Laden im SQLAlchemy ORM dynamisch an?

Ich habe das funktioniert gut mit SQLAlchemy und deklarativen. Ich benutze auch erfolgreich eifrig laden mit den lazy und join_depth Eigenschaften auf den Tabellenrelationen. Dies ist gemäß der SQLAlchemy documentation.

Allerdings legt diese Anordnung die Rekursionstiefe bei 'join_depth' einmal zur Programmladezeit fest ... aber mit den Daten, die ich verwende, weiß ich die Rekursionstiefe, die ich jedes Mal verwenden sollte. Wie kann ich die verwendete Rekursionstiefe pro Abfrage ändern?

hielt ich habe mit dem Master join_depth Eigenschaft auf der Basis ORM Objekt Hantieren, aber das wird nicht funktionieren, da ich eine Multi-Threaded scoped_session Anwendung haben, wo das gefährlich wäre (nicht die Tatsache zu erwähnen, dass Der Parameter ist in SQLAlchemy zur Laufzeit ziemlich schwer zu finden!).

Ich habe auch mit joinedload mit der Abfrage betrachtet, aber sehe nicht, wie man die Tiefe damit variieren.

Ich bin mir auch der 'WITH RECURSIVE' SQL-Syntax in einigen Datenbanken über CTEs bekannt, aber so groß wie es ist, möchte ich das im Moment vermeiden, da einige DBs es immer noch nicht unterstützen (und auch nicht tut SQLAlchemy - zumindest nicht im Moment und nicht ohne viel Dialektanpassung.

Antwort

3

Es gibt keine offizielle Möglichkeit, dies zu tun, aber nach dem Code die folgende Lösung für mich produziert. Ich verwende das Node-Beispiel aus der docs, die Sie verknüpft haben.

class Node(Base): 
    __tablename__ = 'node' 
    id = Column(Integer, primary_key=True) 
    parent_id = Column(Integer, ForeignKey('node.id')) 
    data = Column(String(50)) 
    children = relationship("Node", 
        lazy="joined", 
        join_depth=2) 

zum Zeitpunkt der Erstellung wird die children Eigenschaft ein join_depth von 2 angegeben Dieser Anfangswert in Node.children.property.join_depth aufgezeichnet wird. Wenn Sie diesen Wert jedoch ändern, wird nichts unternommen. Bei init erstellt die Beziehung eine "Strategie" für den Beitritt und kopiert den Wert join_depth. Um die Verknüpfungstiefe der Strategie für die Beziehung zu ändern, legen Sie Node.children.property.strategy.join_depth fest.

>>> engine.echo = True # print generated queries 
>>> session.query(Node).all() # with default join_depth 
SELECT node.id AS node_id, node.parent_id AS node_parent_id, node.data AS node_data, node_1.id AS node_1_id, node_1.parent_id AS node_1_parent_id, node_1.data AS node_1_data, node_2.id AS node_2_id, node_2.parent_id AS node_2_parent_id, node_2.data AS node_2_data FROM node LEFT OUTER JOIN node AS node_2 ON node.id = node_2.parent_id LEFT OUTER JOIN node AS node_1 ON node_2.id = node_1.parent_id 
>>> Node.children.property.strategy.join_depth = 4 # new join depth 
>>> session.query(Node).all() # with new join depth 
SELECT node.id AS node_id, node.parent_id AS node_parent_id, node.data AS node_data, node_1.id AS node_1_id, node_1.parent_id AS node_1_parent_id, node_1.data AS node_1_data, node_2.id AS node_2_id, node_2.parent_id AS node_2_parent_id, node_2.data AS node_2_data, node_3.id AS node_3_id, node_3.parent_id AS node_3_parent_id, node_3.data AS node_3_data, node_4.id AS node_4_id, node_4.parent_id AS node_4_parent_id, node_4.data AS node_4_data FROM node LEFT OUTER JOIN node AS node_4 ON node.id = node_4.parent_id LEFT OUTER JOIN node AS node_3 ON node_4.id = node_3.parent_id LEFT OUTER JOIN node AS node_2 ON node_3.id = node_2.parent_id LEFT OUTER JOIN node AS node_1 ON node_2.id = node_1.parent_id 

Nach Node.children.property.strategy.join_depth Einstellung ändert sich die Anzahl der Verknüpfungen in der generierten Abfrage als auch.

Verwandte Themen