在Sequelize模型中使用Postgres生成列

7

我有一个表格,在数据库引擎中生成预计算的值比在应用程序代码中更有利。为此,我使用了Postgres的生成列功能。SQL如下:

ALTER TABLE "Items"
ADD "generatedValue" DOUBLE PRECISION GENERATED ALWAYS AS (
  LEAST("someCol", "someOtherCol")
) STORED;

这个方案很好,但是我正在使用 Sequelize 操作这个数据库。 我希望找到一种在模型定义中定义该列的方法,使 Sequelize 能够查询它,而不是尝试更新该列的行值,并在同步时创建该列。

class Item extends Sequelize.Model {
  static init(sequelize) {
    return super.init({
      someCol: Sequelize.DOUBLE,
      someOtherColl: Sequelize.DOUBLE,
      generatedValue: // <<<--  What goes here??
    });
  }
}

如何使用Sequelize实现这一点?

我可以将列指定为DOUBLE,Sequelize会读取它,但是在同步时该列不会被正确创建。也许有一些后置同步钩子可以使用?我正在考虑使用afterSync删除该列并重新添加带有生成值语句的列,但是首先需要检测该列是否已经转换,否则可能会丢失数据。(我在每次应用程序启动时运行sync [没有force:true ]。)

任何想法或替代方案都将不胜感激。


也许现在这不是最可行的方案:https://github.com/sequelize/sequelize/issues/12718 - Brad
1个回答

15

在 Sequelize 支持 readOnly 字段和 GENERATED 数据类型之前,您可以通过自定义数据类型来解决 Sequelize 的问题:

const Item = sequelize.define('Item', {
  someCol: { type: DataTypes.DOUBLE },
  someOtherCol: { type: DataTypes.DOUBLE },
  generatedValue: {
    type: 'DOUBLE PRECISION GENERATED ALWAYS AS (LEAST("someCol", "someOtherCol")) STORED',
    set() {
      throw new Error('generatedValue is read-only')
    },
  },
})

使用sync()将在PostgreSQL中正确生成该列,并通过抛出错误来防止在JavaScript中设置generatedValue

假设Sequelize在未更改字段的情况下不尝试更新它,如https://sequelize.org/master/manual/model-instances.html#change-awareness-of-save所指定的那样,则应该可以正常工作。


这很好用,谢谢!还有一个后续问题...在哪里可以正式记录使用字符串作为类型? - Brad
我在文档中找不到任何提及,所以这可能是sequelize未来版本中可能会更改的行为。 - mtkopone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接