繁体   English   中英

使用SQLAlchemy具有多个自引用外键

[英]Using SQLAlchemy with multiple self-referential foreign keys

如果我在关系数据库中有类似双链表的内容,例如:

node_id    left_id    right_id

1          null       2
2          1          3
3          2          null

然后我有一些SQLAlchemy代码,如下所示:

class NodeClass(Base):
    __tablename__ = 'nodes_table'
    node_id = Column(Integer, primary_key=True)
    left_id = Column(Integer, ForeignKey('nodes_table.node_id'))
    right_id = Column(Integer, ForeignKey('nodes_table.node_id'))
    left = relationship('NodeClass') # Wrong
    right = relationship('NodeClass') # Wrong

如果我有node_id 2,我调用NodeClass.left我想收到node_id 1作为回报。 如何配置SQLAlchemy关系以这种方式运行?

更新:

我将举一个例子。 考虑一张人的表,每个人都有一个母亲和一个父亲。

person_id    mother_id    father_id

1            null         null
2            null         null
3            1            2

SQLAlchemy代码:

class PersonClass(Base):
    __tablename__ = 'persons_table'
    person_id = Column(Integer, primary_key=True)
    mother_id = Column(Integer, ForeignKey('persons_table.person_id'))
    father_id = Column(Integer, ForeignKey('persons_table.person_id'))
    mother = relation('PersonClass') # Wrong
    father = relation('PersonClass') # Wrong

下面的代码显示了如何配置关系:

class NodeClass(Base):
    __tablename__ = 'nodes_table'
    node_id = Column(Integer, primary_key=True)

    left_id = Column(Integer, ForeignKey('nodes_table.node_id'))
    left = relationship('NodeClass', remote_side=[node_id],
            primaryjoin=('NodeClass.left_id==NodeClass.node_id'),
            backref=backref("right", uselist=False),
            #lazy="joined", join_depth=9,
            )

但是应该注意的事情很少:

  • 只存储关系的一端,另一端被推断。 这可能不是你想要的,但它管理起来要简单得多,只需设置一方myNode.left = myOtherNode就可以了,另一方( right )将自动设置(因为配置了backref
  • 如果两端都存储( rightleft ),那么
    • 两端都需要在代码中设置,并且必须确保它们是一致的,这可能不是一项微不足道的任务
    • 如果在数据库上计算主键,则链接的两个节点的插入将需要insert-1, insert-2, update-1 ,因为在第一次insert期间它是未知的。

更新:问题的UPDATE部分的示例代码(但仍使用原始类名)。 人们只需要指定primaryjoinuselist=False

class NodeClass(Base):
    __tablename__ = 'nodes_table'
    node_id = Column(Integer, primary_key=True)

    left_id = Column(Integer, ForeignKey('nodes_table.node_id'))
    right_id = Column(Integer, ForeignKey('nodes_table.node_id'))

    left = relationship('NodeClass', primaryjoin = ('NodeClass.left_id == NodeClass.node_id'), use_list=False)
    right = relationship('NodeClass', primaryjoin = ('NodeClass.right_id == NodeClass.node_id'), use_list=False)

暂无
暂无

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

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