4

たとえば、リレーショナルデータベースに二重リンクリストのようなものがある場合はどうなりますか。

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_id1を受け取りたいと思います。このように動作するようにSQLAlchemyリレーションシップを構成するにはどうすればよいですか?

アップデート:

2番目の例を示します。人のテーブルを考えてみましょう。各人には母親と父親がいます。

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
4

1 に答える 1

4

以下のコードは、関係を構成する方法を示しています。

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
  • 両端が保存されている場合(rightおよびleft)、
    • 両端をコードで設定する必要があり、一方はそれらが一貫していることを確認する必要がありますが、これは簡単な作業ではない可能性があります
    • リンクされている2つのノードを挿入するにはinsert-1, insert-2, update-1、データベースで主キーが計算される場合に必要になります。これは、最初のノードでは不明であるためinsertです。

UPDATE:質問のUPDATE部分のサンプルコード(ただし、元のクラス名を使用)。primaryjoinとを指定するだけで済みますuselist=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)
于 2012-05-15T12:14:32.593 に答える