0

我正在查询由第三方维护的专有数据库。该数据库有许多表,每个表都包含大量字段。

我的问题涉及三个感兴趣的表,树、站点和仪表。

树表以简单的树结构描述节点。与其他数据一起,它有一个外键引用它自己的主键。它还有一个 Object_Type 字段和一个 Object_ID 字段。Site 和 Meter 表各有许多字段。

树节点与仪表站点具有一对一的关系。如果 Object_Type 字段为 1,则 Object_ID 字段指的是 Site 表中的主键。如果为 2,则表示 Meter 表中的主键。

按照这个例子https://bitbucket.org/sqlalchemy/sqlalchemy/src/408388e5faf4/examples/declarative_reflection/declarative_reflection.py

我正在使用反射来像这样加载表结构

Base = declarative_base(cls=DeclarativeReflectedBase)

class Meter(Base):
    __tablename__ = 'Meter'

class Site(Base):
    __tablename__ = 'Site'

class Tree(Base):
    __tablename__ = 'Tree'
    Parent_Node_ID = Column(Integer, ForeignKey('Tree.Node_ID'))
    Node_ID = Column(Integer, primary_key=True)
    children = relationship("Tree", backref=backref('parent', remote_side=[Node_ID]))

Base.prepare(engine)

我已经包含了自我参照关系,并且效果很好。如何使用 Object_ID 作为外键添加两个关系,并对 Object_Type 字段进行适当检查?

4

2 回答 2

2

首先是关于反思的说明。我发现自己不依赖反思会好得多。

  1. 它不需要有效的数据库连接来加载/使用您的代码
  2. 它违反了显式优于隐式的python指南。如果您查看代码,最好查看元素(列等),而不是让它们在您的视野之外神奇地创建。

这意味着更多的代码但更易于维护。

我建议的原因至少部分是我在您的帖子中看不到架构。

如果您在代码中创建表和类而不是依赖反射,那么您可以更好地控制映射。

在这种情况下,您要使用多态映射

  1. 如上所述创建一个 TreeNode 类。
  2. 创建 SiteNode 和 MeterNode 作为子类

然后,您的代码将包括以下内容:

mapper(TreeNode,tree_table,polymorphic_on=tree_table.c.object_type)
mapper(SiteNode, site_table,inherits=TreeNode,
                 inherit_condition=site_table.c.node_id==tree_table.c.node_id,
                 polymorphic_identity=1)

希望这可以帮助。

于 2012-07-09T20:28:27.587 回答
1

对于 tree.object_id 是可以引用 Site 或 Meter 的外键,您可以让 Site 和 Meter 从一个公共基表下降,即连接表继承,或者映射到同一个表,即,单表继承,或者正如有人所说,将 Tree 映射到两个不同的表以及一个公共基表。最后一个建议与 TreeNode 已经有一个“类型”字段的想法很吻合。

最后一种可能更容易的选择是直接在 TreeNode 上使用两个外键——site_id 和meter_id,以及两个关系,“meter”和“site”;然后使用 Python @property 返回一个或另一个:

class TreeNode(Base):
   # ...

   @property
   def object(self):
       return self.meter or self.site
于 2012-07-11T17:02:52.120 回答