【问题标题】:sqlalchemy graph database data manipulationsqlalchemy 图数据库数据操作
【发布时间】:2013-02-27 16:11:14
【问题描述】:

我正在设计一个图形数据库结构。一个节点可以是一个人、一个部门等。这就是我添加 nodeType 的原因。节点之间的关系也可以是多种类型。 从下面的代码中,r1 和 r2 被插入到数据库中。当我阅读数据库时,我看到 null null null。这是为什么 ? 我希望看到与.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()

也感谢其他关于代码改进的评论。

【问题讨论】:

  • 您必须指定“读取数据库”的含义。您尝试运行的查询是什么并返回意外的 NULL ?
  • 运行代码后,我使用 SQLiteStudio 读取了数据库。在表关系中我看到: id:1 name:null type:id:null from_id:null to_id:null 与 id:2 相同

标签: database-design graph sqlalchemy


【解决方案1】:

您的代码的问题是您在将节点插入数据库之前尝试使用 Node.id 属性。在您调用 session.flush()session.commit() 之前,新创建的对象没有 id,因为它是生成 ID 的数据库引擎。

因此,SQLAlchemy 的做法是定义Relation 对象和Node 对象之间的关系,并在Relation.__init__ 中分配对象,而不是分配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'))

    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()

【讨论】:

  • 谢谢,现在可以了。当我在代码运行后与解释器交互时,我得到一个线程错误。例如r3 = Relation(n4, rt2.id, n5) 导致线程错误的原因是什么? (对不起,我是新手)谢谢
猜你喜欢
  • 2016-03-12
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 2018-05-02
  • 2012-04-01
  • 2020-10-01
  • 2011-11-16
相关资源
最近更新 更多