Self-Referential Many-to-Many Relationship
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. seealso::
+
+ This section documents a two-table variant of the "adjacency list" pattern,
+ which is documented at :ref:`self_referential`. Be sure to review the
+ self-referential querying patterns in subsections
+ :ref:`self_referential_query` and :ref:`self_referential_eager_loading`
+ which apply equally well to the mapping pattern discussed here.
+
Many to many relationships can be customized by one or both of :paramref:`_orm.relationship.primaryjoin`
and :paramref:`_orm.relationship.secondaryjoin` - the latter is significant for a relationship that
specifies a many-to-many reference using the :paramref:`_orm.relationship.secondary` argument.
:paramref:`_orm.relationship.primaryjoin` and
:paramref:`_orm.relationship.secondaryjoin` arguments.
+.. seealso::
+
+ * :ref:`self_referential` - single table version
+ * :ref:`self_referential_query` - tips on querying with self-referential
+ mappings
+ * :ref:`self_referential_eager_loading` - tips on eager loading with self-
+ referential mapping
+
.. _composite_secondary_join:
Composite "Secondary" Joins
modified preorder has little advantage over an application which can fully
load subtrees into the application space.
+.. seealso::
+
+ This section details the single-table version of a self-referential
+ relationship. For a self-referential relationship that uses a second table
+ as an association table, see the section
+ :ref:`self_referential_many_to_many`.
+
In this example, we'll work with a single mapped
class called ``Node``, representing a tree structure::
``folder_id`` column, which it recognizes as uniquely present on
the "remote" side.
+.. _self_referential_query:
+
Self-Referential Query Strategies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from sqlalchemy.orm import aliased
nodealias = aliased(Node)
- {sql}session.query(Node).filter(Node.data=='subchild1').\
+ session.query(Node).filter(Node.data=='subchild1').\
join(Node.parent.of_type(nodealias)).\
filter(nodealias.data=="child2").\
all()
- SELECT node.id AS node_id,
+ {opensql}SELECT node.id AS node_id,
node.parent_id AS node_parent_id,
node.data AS node_data
FROM node JOIN node AS node_1
lazy="joined",
join_depth=2)
- {sql}session.query(Node).all()
- SELECT node_1.id AS node_1_id,
+ session.query(Node).all()
+ {opensql}SELECT 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,