【问题标题】:Solved: Adding new Column to ORM SQLAlchemy table in a volatile setting已解决:在 volatile 设置中向 ORM SQLAlchemy 表添加新列
【发布时间】:2021-07-02 19:47:33
【问题描述】:

我正在为 MQTT-Broker https://github.com/volkerjaenisch/amqtt_db 开发一个开源持久层

传入的 MQTT 消息是不规则的数据块,因此通常 DB-Backend 是某种对象存储。

我做的很艰难,将 blob 反序列化为类型化的数据列,并将它们存储到一个快速的关系数据库中。我的最终目标是 timescaleDB,但首先我通过 SQLAlchemy 使用一个 API 访问大量数据库。

MQTT 消息是易变的(认为并不总是完整的),因此 DB 方案必须动态调整,例如为新信息添加新列。

First Message:
Time: 1234
Temperature : 23.4

Second Message:
Time: 1245
Temperature : 23.6
Rel Hum : 87 %

我已经使用 SQLalchemy ORM 十多年了,但我总是使用相当静态的数据库。所以我是动态工作的新手。

利用 ORM 从传入的 MQTT 消息的结构中动态构建数据库表是非常可行的,并且非常完美。

但目前我被 MQTT-Packages 中的附加信息的情况所困扰,这些信息用新列扩展了表。

到目前为止我做了什么:

利用 sqlalchemy-migration 可以很容易地将新列动态添加到数据库中的现有表中。在代码中,“topic_cls”是声明性类,“column_def”是 col_name - 类型映射。

from migrate.versioning.schema import Table as MiTable, Column as MiColumn
    
def add_new_colums(self, topic_cls, column_def):
    table_name = str(topic_cls.__table__.name)
    table = MiTable(table_name, self.metadata)
    for col_name, col_type in column_def.items():
        col = MiColumn(col_name, col_type)
        col.create(table)

像魅力一样工作。但是如何让数据库的这些变化反映到声明性类中呢?我试图重新检查表:

new_table = Table(topic_cls.__table__.name, self.metadata, autoload_with=self.engine)

这也有效,但它给了我一个新表,但不是声明性基础。

所以我的愚蠢问题是:

  1. 这是实现我的目标的正确方法吗?
  2. 如何通过检查数据库中已经存在的表来获得声明性类?

“放弃 ORM 并使用 SQL”不是我要寻找的答案。

干杯, 沃尔克

【问题讨论】:

    标签: python sqlalchemy orm


    【解决方案1】:

    找到了一个解决方案,但有点麻烦。

    new_table = Table("test/topic_growth", Base.metadata, autoload_with=self.engine)
    
    Base.metadata.remove(topic_cls.__table__)
    
    new_dcl = type(str(table_name), (Base,), {'__table__': new_table})
    
    Base.metadata._add_table(table_name, None, new_table)
    

    通过检查获得新表后,从元数据中删除旧表条目。 然后使用新表和相同的表名生成一个新的声明性基础。 最后将新表添加到元数据中。

    【讨论】:

      猜你喜欢
      • 2021-06-25
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      • 2019-09-03
      • 1970-01-01
      • 2018-04-17
      • 1970-01-01
      • 2016-07-07
      相关资源
      最近更新 更多