0

グラフデータベースの構造を設計しています。ノードは人、部門などである可能性があります。そのため、nodeTypeを追加しました。ノード間の関係も複数のタイプにすることができます。以下のコードから、r1とr2がデータベースに挿入されます。dbを読み取ると、nullnullnullが表示されます。何故ですか ?.idフィールドに関連する値(n1.id、rt1.id、n2.idなど)が表示されることを期待していました。

from sqlalchemy import MetaData, Table, Column, Integer, ForeignKey, \
    create_engine, String
from sqlalchemy.orm import mapper, relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///dir_graph.sqlite', echo=True)

Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()

class NodeType(Base):
    __tablename__ = 'nodetype'
    id      = Column(Integer, primary_key=True)
    name    = Column(String(20), unique=True)
    nodes   = relationship('Node', backref='nodetype')

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "Nodetype: %s" % (self.name)


class Node(Base):
    __tablename__ = 'node'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    type_id = Column(Integer,
                        ForeignKey('nodetype.id')) 

    def __init__(self, _name, _type_id):
        self.name = _name
        self.type_id = _type_id

class Relation(Base):
    __tablename__ = 'relation'

    id      = Column(Integer, primary_key=True)
    name    = Column(String(20), unique=True)
    type_id = Column(Integer,
                        ForeignKey('relationtype.id')) 

    from_id = Column(Integer,
                        ForeignKey('node.id'))

    to_id = Column(Integer,
                        ForeignKey('node.id'))


    def __init__(self, _fromNode, _type_id, _toNode):
            self.from_id = _fromNode
            self.type_id =  _type_id
            self.to_id   = _toNode

class RelationType(Base):
    __tablename__ = 'relationtype'

    id             = Column(Integer, primary_key=True)
    name           = Column(String(20), unique=True)
    description    = Column(String(30), unique=True)

    relations      = relationship('Relation', backref='relationtype')

    def __init__(self, _name):  
        self.name = _name

    def description(self, _description):
        self.description = _description  
Base.metadata.create_all(engine)

nt1 = NodeType('nt1')
nt2 = NodeType('nt2')

n1 = Node('n1type1', 1)
n2 = Node('n2type1', 1)
n3 = Node('n3type1', 1)
n4 = Node('n4type2', 2)
n5 = Node('n5type2', 2)

rt1 = RelationType('rt1')
rt2 = RelationType('rt2')
rt3 = RelationType('rt3')

r1 = Relation(n1.id,rt1.id,n2.id)
r2 = Relation(n3.id,rt2.id,n5.id)

session.add_all([nt1,nt2,n1,n2,n3,n4,n5,rt1,rt2,rt3,r1,r2])
session.commit()

コードの改善に関する他のコメントも高く評価されています。

4

1 に答える 1

2

コードの問題は、ノードがDBに挿入される前にNode.idプロパティを使用しようとすることです。session.flush()またはを呼び出すまでsession.commit()、新しく作成されたオブジェクトにはIDがなく、IDを生成するのはDBエンジンであるためできません。

したがって、これを行うSQLAlchemyの方法は、Relationオブジェクトとオブジェクトの間の関係を定義し、 IDを割り当てるのではなくNode、でオブジェクトを割り当てることです。Relation.__init__ちょうどこのような:

from sqlalchemy import MetaData, Table, Column, Integer, ForeignKey, \
    create_engine, String
from sqlalchemy.orm import mapper, relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///dir_graph.sqlite', echo=True)

Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()


class NodeType(Base):
    __tablename__ = 'nodetype'
    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    nodes = relationship('Node', backref='nodetype')

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "Nodetype: %s" % self.name


class Node(Base):
    __tablename__ = 'node'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    type_id = Column(Integer,
                     ForeignKey('nodetype.id'))


    def __init__(self, _name, _type_id):
        self.name = _name
        self.type_id = _type_id


class Relation(Base):
    __tablename__ = 'relation'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    type_id = Column(Integer,
                     ForeignKey('relationtype.id'))

    from_id = Column(Integer,
                     ForeignKey('node.id'))

    to_id = Column(Integer,
                   ForeignKey('node.id'))

    from_node = relationship(Node, primaryjoin=Node.id == from_id)
    to_node = relationship(Node, primaryjoin=Node.id == to_id)

    def __init__(self, _fromNode, _type_id, _toNode):
        self.from_node = _fromNode
        self.type_id = _type_id
        self.to_node = _toNode


class RelationType(Base):
    __tablename__ = 'relationtype'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    description = Column(String(30), unique=True)

    relations = relationship('Relation', backref='relationtype')

    def __init__(self, _name):
        self.name = _name

    def description(self, _description):
        self.description = _description


Base.metadata.create_all(engine)

nt1 = NodeType('nt1')
nt2 = NodeType('nt2')

n1 = Node('n1type1', 1)
n2 = Node('n2type1', 1)
n3 = Node('n3type1', 1)
n4 = Node('n4type2', 2)
n5 = Node('n5type2', 2)

rt1 = RelationType('rt1')
rt2 = RelationType('rt2')
rt3 = RelationType('rt3')

r1 = Relation(n1, rt1.id, n2)
r2 = Relation(n3, rt2.id, n5)

session.add_all([nt1, nt2, n1, n2, n3, n4, n5, rt1, rt2, rt3, r1, r2])
session.commit()
于 2013-02-27T18:14:26.743 に答える