SQLAlchemy 闭包表关系定义

2024-05-06

我最近开始使用 SQL Alchemy 开展一个涉及攀岩区域和路线的项目。区域是分层的,因为单个区域可以包含多个区域,而多个区域又可以包含其他区域。路线直接与单个区域关联,但也与该区域的父区域关联,等等。

为了实现这一点,我选择使用Bill Karwin 的闭合表 http://karwin.blogspot.com/2010/03/rendering-trees-with-closure-tables.html。在闭包表实现中,创建第二个表来存储祖先/后代信息。添加节点时会创建自引用行,并为树中的每个祖先创建一行。

表结构如下(简化):

-- area --
area_id
name

-- area_relationship --
ancestor
descendent

-- route --
route_id
area_id
name

样本数据:

-- area --
1, New River Gorge
2, Kaymoor
3, South Nuttall
4, Meadow River Gorge

-- area_relationship (ancestor, descendent) --
1, 1 (self-referencing)
2, 2 (self-referencing)
1, 2 (Kaymoor is w/i New River Gorge)
3, 3 (self-referencing)
1, 3 (South Nutall is w/i New River Gorge)
4, 4 (self-referencing)

-- route (route_id, area_id, name)
1, 2, Leave it to Jesus
2, 2, Green Piece
3, 4, Fancy Pants

要查询给定路线(树上)的所有区域,我可以执行:

SELECT area.area_id, area.name
FROM route 
    INNER JOIN area_relationship ON route.area_id = area_relationship.descendent
    INNER JOIN area ON area.area_id = area_relationship.ancestor
WHERE route.route_id = 1

同样,我可以使用以下命令查询特定区域(包括后代区域)中的所有路线:

SELECT route.route_id, route.name
FROM area
    INNER JOIN area_relationship ON area.area_id = area_relationship.ancestor
    INNER JOIN route ON route.area_id = area_relationship.descendent
WHERE area.area_id = 1

在 SQL Alchemy 中,我创建了一个关系和两个表来处理这些关系:

area_relationship_table = Table('area_relationship', Base.metadata,
  Column('ancestor', Integer, ForeignKey('area.area_id')),
  Column('descendent', Integer, ForeignKey('area.area_id'))
)

DbArea 类 -

class DbArea(Base):

    __tablename__ = 'area'

    area_id = Column(Integer, primary_key = True)
    name = Column(VARCHAR(50))
    created = Column(DATETIME)

    area_relationship_table.c.ancestor])

    descendents = relationship('DbArea', backref = 'ancestors',
        secondary =  area_relationship_table,
        primaryjoin = area_id == area_relationship_table.c.ancestor,
        secondaryjoin = area_id == area_relationship_table.c.descendent)

DbRoute 类 -

    class DbRoute(Base):

        __tablename__ = 'route'

        route_id = Column(Integer, primary_key = True)
        area_id = Column(Integer, ForeignKey('area.area_id'))
        name = Column(VARCHAR(50))
        created = Column(DATETIME)

        area = relationship("DbArea")

        areas = relationship('DbArea', backref = 'routes',
            secondary = area_relationship_table,
            primaryjoin = area_id == area_relationship_table.c.ancestor,
            secondaryjoin = area_id == area_relationship_table.c.descendent,
            foreign_keys=[area_relationship_table.c.ancestor,
            area_relationship_table.c.descendent])

目前,我可以使用 DbRoute 中的区域关系来确定各个路线的区域。但是,当我尝试在 DbArea 中使用 backref 'routes' 时,出现以下错误:

sqlalchemy.exc.StatementError: 在映射器Mapper|DbArea|area... 上没有配置列route.area_id... (原始原因:UnmappedColumnError: 在映射器Mapper|DbArea|area... 上没有配置列route.area_id...) 'SELECT 路由.route_id AS 路由_路由_id、路由.area_id AS 路由_区域_id、路由.name AS 路由_名称、route.created AS 路由_创建 \nFROM 路由、area_relationship \nWHERE %s = area_relationship.descendent AND route.area_id = area_relationship.ancestor' [immutabledict({}) ]

我猜测我可能需要向 DbArea 添加一些内容来建立关系,但在尝试了一些不同的选项后无法确定解决方案。


在发布到 SQL Alchemy Google Group 并收到一些信息后迈克尔·拜尔的大力帮助 https://groups.google.com/group/sqlalchemy/browse_thread/thread/53ac06a4eead97d3/6a010eedb7a76aca#6a010eedb7a76aca,我在 DbRoute 类中得到了以下区域关系的定义

areas = relationship('DbArea',
    backref = backref('routes', order_by = 'DbRoute.name'),
    secondary = area_relationship_table,
    primaryjoin = area_id == area_relationship_table.c.descendent,
    secondaryjoin = DbArea.area_id == area_relationship_table.c.ancestor,
    innerjoin = True, order_by = DbArea.name,
    foreign_keys =
       [area_relationship_table.c.ancestor,
            area_relationship_table.c.descendent]) 

关键在于正确定义连接。现在,我可以轻松地从路线实例中查找祖先树中的区域,或者从某个区域中查找后代树中的所有路线。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQLAlchemy 闭包表关系定义 的相关文章

随机推荐

  • html画布绘图显示出来

    我确信这个问题在我还找不到答案之前就已经被问过 我想通过在顶部绘制另一个白色矩形来擦除黑色矩形的一部分 但是许多原始黑色矩形显示出来 就像正在平均一样 canvas document getElementById canvas contex
  • Ansible 和硬件检查

    我必须使用 ansible 检查 Linux 机器上的不同硬件和配置元素 我完全不确定如何做到这一点 RAM 磁盘空间 DNS CPU 我知道我几乎可以找到我想要的所有事实都在 ansible 中 但我不明白如何使用它 例如 我必须检查 R
  • 如何从 coxme 包中的 lmekin 对象中提取 p 值

    我希望能够查看 coxme 包生成的 lmekin 对象的 p 值 eg model lmekin formula height score sex age 1 IID data phenotype df varlist kinship m
  • weak_ptr、make_shared 和内存释放

    一个控制块shared ptr当至少有一个时保持存活weak ptr展示 如果共享指针是用以下命令创建的make shared这意味着对象的整个内存都保持分配状态 对象本身被正确破坏 但由于对象的控制块和内存被分配在一个块中 如make s
  • 如何在Python中每次运行脚本时增加变量?

    我有一个 Python 脚本 我想在每次运行时增加一个全局变量 这可能吗 使用外部文件很容易做到这一点 您可以创建一个函数来为您执行此操作 这样您就可以根据需要将多个文件用于多个变量 尽管在这种情况下您可能想要研究某种序列化并将所有内容存储
  • 在 ionic 3 应用程序中找不到命名空间“google”

    在我尝试在项目中使用 google 变量后 任何人都可以帮我解决这个错误 我进入了 ionic 3 应用程序 npm install save types google maps 将以下内容添加到我的 package json 中 type
  • winpdb 不适用于 python 3.3

    我无法让 rpdb2 与 python 3 3 一起运行 但根据多个来源 这应该是可能的 rpdb2 d myscript py A password should be set to secure debugger client serv
  • 是否有中欧通用的 TimeZoneInfo?

    是否有针对中欧的通用 TimeZoneInfo 将 CET 和 CEST 纳入考虑 我有一个应用程序正在执行以下操作 TimeZoneInfo tzi TimeZoneInfo FindSystemTimeZoneById Central
  • 通过pip安装lxml时出错:需要Microsoft Visual C++ 14.0

    我使用的是 Windows 10 机器 最近从 python 2 7 迁移到 3 5 当尝试通过 pip 安装 lxml 时 它会停止并抛出此错误消息 构建 lxml etree 扩展错误 需要 Microsoft Visual C 14
  • 在Python子目录中创建文件?

    在我的 Python 脚本中 我需要在子目录中创建一个新文件而不更改目录 并且需要从当前目录不断编辑该文件 My code os mkdir datetime dst for ip in open list txt with open ip
  • 使用加权概率和值查找数组中的项目

    上周我正在做的一个简单程序遇到了一些问题 这里有人帮助了我 现在我遇到了另一个问题 我目前有这个代码 var findItem function desiredItem var items item rusty nail probabili
  • Mac OS X 文件关联有效,但文件图标未更改

    我使用 Qt 5 3 2 开发了一个 Mac 应用程序 该应用程序处理具有特定扩展名的文件 比方说 xyz 我创建了一个名为 XYZ icns 的图标文件 并将其添加到我的应用程序包资源文件夹中 MyApp app Contents Res
  • 在自动触发的默认侦听器之前触发 Hibernate 自定义事件侦听器

    我创建了一个自定义 Hibernate 事件监听器 扩展了 org hibernate event PreInsertEventListener 自定义侦听器会重写 onPreInsert 方法 并在使用 DAO 将 联系人 实体保存到数据
  • 如何在android中动态添加项目到listview

    有谁能够帮助我 我正在尝试在 Android 中创建一个 ListView 并且我正在尝试使用代码 不使用 XML 将项目加载到其中 这是我到目前为止的代码 tweetList ListView this findViewById R id
  • 猪如何过滤不同的对(对)

    我是猪的新手 我有一个 Pig 脚本 它在两个元素之间生成制表符分隔的对 每行一对 例如 John Paul Tom Nik Mark Bill Tom Nik Paul John 我需要过滤掉重复的组合 如果我使用 DISTINCT 我会
  • 如何在列表视图中每行右侧显示 4 个图标

    我想在列表视图的每一行右侧设置 3 个图标 我正在制作购物应用程序 我希望在列表视图中用户选择任何产品时 这样他 她可以以 3 种方式查看产品 就像用户选择图标一样1 这样用户可以在网格视图中看到产品 如果用户选择图标 2 这样用户可以在图
  • Visual Studio 2017 ASP.Net 发布独立的 Dot Net Core 应用程序

    我在 Visual Studio 2017 中有一个 Net Core ASP Net 应用程序 我正在尝试对该应用程序进行独立部署 如果我从 CLI 运行以下命令 它会完全按照我想要的方式工作并生成 exe dotnet publish
  • 将 H264 视频转换为原始 YUV 格式

    是否可以使用 ffmpeg 从 H264 编码视频创建原始 YUV 视频 我想用 matlab 打开视频并逐帧访问 Luma Cb 和 Cr 分量 是的 您可以 您只需指定像素格式即可 要获取格式的完整列表 ffmpeg pix fmts
  • 使用基于 ConvLSTM2D 的 Keras 模型从较低分辨率图像估计高分辨率图像

    我正在尝试使用以下内容ConvLSTM2D从低分辨率图像序列估计高分辨率图像序列的架构 import numpy as np scipy ndimage matplotlib pyplot as plt from keras models
  • SQLAlchemy 闭包表关系定义

    我最近开始使用 SQL Alchemy 开展一个涉及攀岩区域和路线的项目 区域是分层的 因为单个区域可以包含多个区域 而多个区域又可以包含其他区域 路线直接与单个区域关联 但也与该区域的父区域关联 等等 为了实现这一点 我选择使用Bill