I am trying to create a table attribute via a relationship. It needs to be
ready-only and return the nodes (peer) where which have at least one common
left node (predecessor). I am able to construct a query (shown below at the
bottom) but I am having difficultly working out where I am going wrong when
translating it into a relationship (if it is at all possible). Below is
some code to demonstrate what I am trying to achieve. Many thanks.
from sqlalchemy import (select, create_engine, Integer, ForeignKey, String,
Column, Table)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
import random
Base = declarative_base()
node_to_node = Table("node_to_node", Base.metadata,
Column("left_node_id", Integer,
ForeignKey("node.id"), primary_key=True),
Column("right_node_id", Integer, ForeignKey("node.id"),
primary_key=True)
)
class Node(Base):
__tablename__ = 'node'
id = Column(Integer, primary_key=True)
label = Column(String)
right_nodes = relationship("Node",
secondary=node_to_node,
primaryjoin=id==node_to_node.c.left_node_id,
secondaryjoin=id==node_to_node.c.right_node_id,
backref= "left_nodes"
)
# This is my attempt to create a sibling relationship based on a query below
sibling_nodes = relationship("Node",
secondary=node_to_node,
primaryjoin=id==node_to_node.c.right_node_id,
secondaryjoin=node_to_node.c.left_node_id.in_(
select([node_to_node.c.left_node_id]).where(
node_to_node.c.right_node_id ==
id)),
viewonly=True,
)
def __repr__(self):
return "({0}) {1}".format(self.id, self.label)
engine = create_engine('sqlite:///:memory:', echo=False)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
predecessors = ["one", "two", "three", "four", "five"]
peers = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
successors = ["1", "2", "3", "4", "5"]
session.add_all([Node(label=l) for l in predecessors + peers + successors])
for p in peers:
r = session.query(Node).filter(Node.label == p).first()
r.left_nodes = session.query(Node).filter(Node.label.in_(
random.sample(predecessors, 1))).all()
session.commit()
for s in successors:
r = session.query(Node).filter(Node.label == s).first()
r.left_nodes = session.query(Node).filter(Node.label.in_(
random.sample(peers, 1))).all()
session.commit()
# The query reporting to p is the result I want and I have tried
unsuccessfully to translate it into a relationship
# see above sibling_nodes in Node class
for l in peers:
r = session.query(Node.id).filter(Node.label == l).scalar()
p = session.query(Node).filter(node_to_node.c.right_node_id ==
Node.id).filter(node_to_node.c.left_node_id.in_(
session.query(node_to_node.c.left_node_id).filter(
node_to_node.c.right_node_id ==
r))).all()
print(p)
#
=============================================================================
# SELECT node.id AS node_id, node.label AS node_label
# FROM node, node_to_node
# WHERE node_to_node.right_node_id = node.id AND node_to_node.left_node_id
IN
# (SELECT node_to_node.left_node_id AS node_to_node_left_node_id
# FROM node_to_node
# WHERE node_to_node.right_node_id = ?)
#
=============================================================================
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
To post example code, please provide an MCVE: Minimal, Complete, and Verifiable
Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.