数据库管理
ORM基类
以下是数据库ORM基类的定义
# Create a Base class using the custom MetaData
# Base = declarative_base(metadata=meta) # SQLAlchemy V2 版本推荐使用基于类DeclarativeBase的扩展来取代原来的declarative_base()方法
class DBBase(DeclarativeBase):
"""
Attributes:
metadata: The metadata object for the database. 等价于 declarative_base(metadata=meta)的方法
__table_args__: The table arguments for the database. Specify the schema for the database here.
"""
metadata = meta
__table_args__ = {"schema": "tfrserver"}
create_timestamp: Mapped[int] = Column(BigInteger, nullable=False, default=now_timestamp)
update_timestamp: Mapped[int] = Column(BigInteger, nullable=False, default=now_timestamp, onupdate=now_timestamp)
需要注意:
- 随着SQLAlchemy V2版本的全面升级,推荐使用基于类DeclarativeBase的扩展来取代原来的declarative_base()方法
- 通过
__table_args__属性可以指定数据库的schema。但需要注意,在子类中存在定义索引的需求,按SQLAlchemy的实现,常见地有两种方式来实现索引定义,分别如下:
方式一:在数据类中使用__table_args__属性定义索引
class DocMetadata(DBBase):
__tablename__ = "doc_metadata"
doc_id: Mapped[int] = Column(
Integer,
primary_key=True,
autoincrement=False,
nullable=False,
comment="指向TFRobot框架中的Document的ID。完整路径为`doc.documents.doc_id`,`doc`是Schema,`documents`是表名",
)
meta: Mapped[dict] = Column("meta", JSONB)
__table_args__ = (
Index(None, "meta", postgresql_using='gin'), {'schema': 'tfrserver'}
)
方式二:使用Index类定义索引
class DocMetadata(DBBase):
__tablename__ = "doc_metadata"
doc_id: Mapped[int] = Column(
Integer,
primary_key=True,
autoincrement=False,
nullable=False,
comment="指向TFRobot框架中的Document的ID。完整路径为`doc.documents.doc_id`,`doc`是Schema,`documents`是表名",
)
meta: Mapped[dict] = Column("meta", JSONB)
Index(None, DocMetadata.meta, postgresql_using='gin')
因为在基类中已经使用了__table_args__属性,所以推荐使用方式二进行索引的定义。如果一定要使用方式一,需要在子类中使用__table_args__属性时,额外添加{"schema": "tfrserver"}schema字段。否则会导致子类的表没有schema属性,从而建表时错误地在default schema下创建表。
视图类
参考 Sqlalchemy官方创建View的文档 可以进行视图的定义。但需要注意,在通过这种方式定义完视图类后,select语句中查询参数的指定需要有所调整:
对于表结构,查询时可以直接使用类名配合.查询属性。举例如下:
select(User).where(User.name == 'ed')
但对于视图类结构,需要在视图类后添加一个.c来先获取Columns,举例如下:
select(UserView.c).where(UserView.c.name == 'ed')
数据库迁移
目前主要是通过ORM类的映射,配合Alembic进行迁移。但需要注意,如果使用数据库视图功能,Alembic不会自动迁移,需要手动维护视图的定义与结构。