简体   繁体   English

有向图-SQLAlchemy ORM

[英]Directed Graph - SQLAlchemy ORM

I am trying to create a directed graph (with backward references) via SQLAlchemy; 我试图通过SQLAlchemy创建一个有向图(带有向后引用); how can I get the desired output listed below? 如何获得下面列出的所需输出? [ see section titled 'Desired Output' ] [ 参见标题为“所需输出”的部分 ]


Example code: 示例代码:

example_db.py example_db.py

from sqlalchemy import Column, Integer, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref

Base = declarative_base()

node_connector = Table('node_connector', Base.metadata, 
    Column('from_node_handle', Integer, ForeignKey('node.handle')),
    Column('to_node_handle', Integer, ForeignKey('node.handle')))


class Node(Base):
    __tablename__ = 'node'
    handle = Column(Integer, nullable=False, primary_key=True)
    next_nodes = relationship('Node',
        secondary=node_connector,
        foreign_keys=[node_connector.c.to_node_handle],
        backref=backref("previous_nodes",
            foreign_keys=[node_connector.c.from_node_handle]))

test/example_db_test.py 测试/ example_db_test.py

Module being executed 正在执行的模块

from sqlalchemy import create_engine, event
from sqlalchemy.engine import Engine
from sqlalchemy.orm import sessionmaker
import unittest

from ..example_db import Base, Node

class TestNodeDB(unittest.TestCase):

    def setUp(self):
        engine = create_engine('sqlite:///:memory:', echo=False)    
        SessionMaker = sessionmaker(bind=engine)
        self.__session = SessionMaker()
        Base.metadata.create_all(engine)

    def test_node_creation(self):
        node_a = Node()
        node_b = Node()
        node_c = Node()
        self.__session.add(node_a)
        self.__session.add(node_b)
        self.__session.add(node_c)
        node_a.next_nodes.append(node_b)
        node_b.next_nodes.append(node_c)
        self.__session.commit()

        nodes = self.__session.query(Node)

        for node in nodes:
            print "Node handle " + str(node.handle) + ":"
            for next_node in node.next_nodes:
                print "\t next node handle " + str(next_node.handle)
            for previous_node in node.previous_nodes:
                print "\t previous node handle " + str(previous_node.handle)



if __name__ == "__main__":
    unittest.main()

Output 产量

Actual output 实际产量

Node handle 1:
Node handle 2:
     next node handle 2
     previous node handle 2
Node handle 3:
     next node handle 3
     previous node handle 3

Desired Output 期望的输出

Node handle 1:
     next node handle 2
Node handle 2:
     next node handle 3
     previous node handle 1
Node handle 3:
     previous node handle 2

How can I get this desired output? 如何获得所需的输出?

Thanks! 谢谢!

SQLAlchemy even has documentation on this: Self-Referential Many-to-Many Relationship , which covers exactly what you want. SQLAlchemy甚至对此有文档: 自引用多对多关系 ,它准确地覆盖了您想要的内容。 Basically, you got it almost right, just instead of using the foreign_keys setting use primaryjoin and secondaryjoin : 基本上,您几乎可以正确地做到这一点,只是使用primaryjoinsecondaryjoin而不是使用foreign_keys设置:

next_nodes = relationship('Node',
    secondary=node_connector,
    primaryjoin=handle==node_connector.c.to_node_handle,
    secondaryjoin=handle==node_connector.c.from_node_handle,
    backref="previous_nodes",
    )

Now your tests work. 现在您的测试工作了。 One additional detail: You don't need to add node_b and node_c : They are added through the casacde: If node_a is in the session and you add something to a configured relationship, they will also be added. 一个额外的细节:您不需要添加node_bnode_c :它们是通过casacde添加的:如果node_a在会话中,并且您向配置的关系中添加了一些东西,它们也将被添加。 Also you don't need to commit : When you query the session figures it must first flush, then query. 另外,您不需要commit :查询会话图时,必须先刷新然后查询。

And also pay attention that you need to watch over loading strategies here. 另外请注意,您需要在这里注意加载策略。 Take the example on Configuring Self-Referential Eager Loading to figure out a way that works for you. 以“ 配置自引用渴望加载 ”为例,找出适合您的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM