如何使用 postgres 在 sequelize 中将 m:n 关联表 id 从整数迁移到 uuid?

How to migrate m:n association table ids from integer to uuid in sequelize with postgres?

提问人:J. Unkrass 提问时间:11/4/2023 最后编辑:J. Unkrass 更新时间:11/4/2023 访问量:36

问:

我有两个模型,书和作者,有很多对多的关联。我最初将它们都实现为具有自动递增的整数 ID,但现在我想将两者都切换到 UUID。我将 UUID 数据类型添加到关联中:

// models/book.js
const { Model } = require('sequelize')

module.exports = (sequelize, DataTypes) => {
  class Book extends Model {
    static associate(models) {
      Book.belongsToMany(models.Author, {
        as: 'authors',
        through: 'BookAuthors',
        foreignKey: {
          allowNull: false,
          name: 'bookId',
          type: DataTypes.UUID
        }
      })
    }
  }
  
  Book.init(
    {
      title: {
        type: DataTypes.STRING,
        allowNull: false
      }
    },
    {
      sequelize,
      modelName: 'Book'
    }
  )
  return Book
}
// models/author.js
const { Model } = require('sequelize')

module.exports = (sequelize, DataTypes) => {
  class Author extends Model {
    static associate(models) {
      Author.belongsToMany(models.Book, {
        through: 'BookAuthors',
        foreignKey: {
          allowNull: false,
          name: 'authorId',
          type: DataTypes.UUID
        }
      })
    }
  }
  Author.init(
    {
      name: {
        type: DataTypes.STRING(75),
        allowNull: false,
        unique: true
      },
      biography: DataTypes.TEXT
    },
    {
      sequelize,
      modelName: 'Author'
    }
  )

  return Author
}

在设置数据库的迁移中,我将两个 id 属性都更改为:

id: {
  allowNull: false,
  defaultValue: Sequelize.UUIDV4,
  primaryKey: true,
  type: Sequelize.UUID
}

我不关心表中的数据,我已经删除了表并使用新代码重新创建了它,但是启动服务器失败并出现以下错误:

Key columns "authorId" and "id" are of incompatible types: integer and uuid.

执行语句时:

CREATE TABLE IF NOT EXISTS "BookAuthors" ("createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "authorId" INTEGER NOT NULL REFERENCES "Authors" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "bookId" UUID NOT NULL REFERENCES "Books" ("id") ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY ("authorId","bookId"));

Afaik,关联表是 Sequelize 在调用时自动创建的。那么,为什么它接受书籍的 UUID,而不接受作者的 UUID?db.sequelize.sync()

node.js PostgreSQL Express 续集.js

评论

0赞 Anatoly 11/4/2023
请显示整个模型定义,我也没有得到它,你使用迁移或方法(你都提到了)sync
0赞 J. Unkrass 11/4/2023
我更新了模型定义。我想使用迁移来定义和更新我的表,但是我读到使用 sequelize 创建关联表的方法是在模型中定义关联(通过),然后调用 .你会推荐什么?sequelize.sync()
1赞 Anatoly 11/4/2023
对于实际的生产项目,我当然建议使用迁移。如果它只是简单的开发/宠物项目,那么也许它足以用于简单sync
0赞 J. Unkrass 11/4/2023
谢谢!在您的帮助下,我完全切换到了迁移,并且还为关联表添加了迁移。在模型中声明 PK 是缺失的部分,现在它可以工作了

答:

1赞 Anatoly 11/4/2023 #1

您没有在模型中明确指示 PK,因为现在您希望使用默认数据库类型(整数)以外的其他类型来定义它们:

书本型号:

Book.init(
    {
      id: {
        allowNull: false,
        defaultValue: Sequelize.UUIDV4,
        primaryKey: true,
        type: Sequelize.UUID
      },
      title: {
        type: DataTypes.STRING,
        allowNull: false
      }
    },
    {
      sequelize,
      modelName: 'Book'
    }
  )

作者模型:

Author.init(
    {
      id: {
        allowNull: false,
        defaultValue: Sequelize.UUIDV4,
        primaryKey: true,
        type: Sequelize.UUID
      },
      name: {
        type: DataTypes.STRING(75),
        allowNull: false,
        unique: true
      },
      biography: DataTypes.TEXT
    },
    {
      sequelize,
      modelName: 'Author'
    }
  )