Sequelize - 模型和迁移

Posted

技术标签:

【中文标题】Sequelize - 模型和迁移【英文标题】:Sequelize - Model and Migrations 【发布时间】:2020-11-09 02:14:57 【问题描述】:

[已解决!]

我在互联网上进行了很多研究,并发现了一些与我类似的问题。但是,我找不到解决问题的正确方法。请帮忙。

我正在使用 Sequelize v6。我在使用模型和迁移时遇到了一些麻烦。

我做了什么:

我使用 sequelize cli 生成了角色模型。它在models/role.js 中为我提供了以下代码。

"use strict";
const  Model  = require("sequelize");

module.exports = (sequelize, DataTypes) => 
  class Role extends Model 
    static associate(models) 
      // define association here
    
  

  Role.init(
    
      name: DataTypes.STRING,
      description: DataTypes.STRING,   ,
    
      sequelize,
      modelName: "roles",
    
  );

  return Role;
;

我还在migrations/timestamp-create-role.js 中获得了该模型的迁移文件。

"use strict";

module.exports = 
  up: async (queryInterface, Sequelize) => 
    await queryInterface.createTable(
      "roles", // <- I've changed this from Roles to roles because I want the mysql convention.
      
        roleId: 
          allowNull: false,
          autoIncrement: true,
          field: "role_id",
          primaryKey: true,
          type: Sequelize.INTEGER,
        ,
        name: 
          allowNull: false,
          type: Sequelize.STRING(30),
        ,
        description: 
          type: Sequelize.STRING(50),
        ,
        createdAt: 
          allowNull: false,
          field: "created_at",
          type: Sequelize.DATE,
        ,
        updatedAt: 
          allowNull: false,
          field: "updated_at",
          type: Sequelize.DATE,
        ,
      ,
      
        underscored: true,
      
    );
  ,

  down: async (queryInterface, Sequelize) => 
    await queryInterface.dropTable("roles");
  ,
;

我在 MySQL 中得到了什么

通过运行上述迁移,我得到了roles 包含以下列的表:

role_id, name, created_at, updated_at 很好。这就是我想要的 MySQL 数据库。

阅读角色

/controllers/roles.js

const Role = require("../models").roles;
const catchAsync = require("../middlewares/catchAsync");

exports.findAll = catchAsync(async (req, res) => 
  const roles = await Role.findAll();

  return res.status(200).json(
    status: "success",
    data: 
      roles,
    ,
  );
);

我哪里不好

通过上面的实现,我在控制台上得到了这个错误。

Executing (default): SELECT `id`, `name`, `description`, `createdAt`, `updatedAt` FROM `roles` AS `roles`;
SequelizeDatabaseError: Unknown column 'id' in 'field list'
    at Query.formatError (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:239:16)
    at Query.run (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:54:18)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async /home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/sequelize.js:619:16
    at async MySQLQueryInterface.select (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/abstract/query-interface.js:938:12)
    at async Function.findAll (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/model.js:1741:21)
    at async /home/hello-world/Thesis/SMS-API/src/controllers/roles.js:5:17
    at async /home/hello-world/Thesis/SMS-API/src/middlewares/catchAsync.js:4:7

另一次尝试

我已经修改了models/role.js,如下所示。

Role.init(
    
      role_id: 
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: DataTypes.INTEGER,
      ,
      name: DataTypes.STRING,
      description: DataTypes.STRING,
      created_at: DataTypes.DATE,
      updated_at: DataTypes.DATE,
    

下一次尝试,下一次错误

通过上面的修改,我得到了新的错误。

Executing (default): SELECT `role_id`, `name`, `description`, `created_at`, `updated_at`, `createdAt`, `updatedAt` FROM `roles` AS `roles`;
SequelizeDatabaseError: Unknown column 'createdAt' in 'field list'
    at Query.formatError (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:239:16)
    at Query.run (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:54:18)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async /home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/sequelize.js:619:16
    at async MySQLQueryInterface.select (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/abstract/query-interface.js:938:12)
    at async Function.findAll (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/model.js:1741:21)
    at async /home/hello-world/Thesis/SMS-API/src/controllers/roles.js:5:17
    at async /home/hello-world/Thesis/SMS-API/src/middlewares/catchAsync.js:4:7

帮助

我尝试了很多方法都无法解决我的问题。所以,请帮忙。我想要 MySQL 级别的 MySQL 命名约定 underscore 和代码级别的 javascript 命名约定。

非常感谢。

【问题讨论】:

【参考方案1】:

我已经解决了我的问题。我现在可以为他们的特定世界使用每个命名约定:under_score 用于 MySQL,camelCase 用于 JavaScript。

因此,如果将来有人遇到同样的问题,我会在这里写下我的解决方案。

我正在使用sequelize-cli 创建迁移、模型和播种机。您可以查看here。

迁移

Migration 只负责创建/更改/删除表和列。 它只访问数据库。

migrations/timestamp-create-role-table.js

"use strict";

module.exports = 
  up: async (queryInterface, Sequelize) => 
    await queryInterface.createTable("roles", 
      roleId: 
        allowNull: false,
        autoIncrement: true,
        field: "role_id",
        primaryKey: true,
        type: Sequelize.INTEGER,
      ,
      name: 
        allowNull: false,
        type: Sequelize.STRING(30),
      ,
      description: 
        type: Sequelize.STRING(50),
      ,
      createdAt: 
        allowNull: false,
        field: "created_at",
        type: Sequelize.DATE,
      ,
      updatedAt: 
        allowNull: false,
        field: "updated_at",
        type: Sequelize.DATE,
      ,
    );
  ,

  down: async (queryInterface, Sequelize) => 
    await queryInterface.dropTable("roles");
  ,
;

通过运行上述迁移脚本,我在物理数据库中获得了roles 表和以下列。 role_id, name, description, created_at, updated_at

播种机

Seeder 将使用初始测试数据填充您的表格。我已经填写了我的roles 表,如下所示。

seeders/timestamp-roles-table-seeder.js

"use strict";

const roles = [
  "official",
  "office",
  "admin"
].map((role) => 
  return 
    name: role,
    created_at: new Date(),
    updated_at: new Date(),
  ;
);

module.exports = 
  up: async (queryInterface, Sequelize) => 
    await queryInterface.bulkInsert("roles", roles);
  ,

  down: async (queryInterface, Sequelize) => 
    await queryInterface.bulkDelete("roles", null, );
  ,
;

型号

创建表并填充初始数据后,我需要创建Role 模型以用作 MySQL 和 JavaScript 之间的桥梁

models/role.js

"use strict";
const  Model  = require("sequelize");

module.exports = (sequelize, DataTypes) => 
  class Role extends Model 
    static associate(models) 
      // define association here
    
  

  Role.init(
    
      roleId: 
        allowNull: false,
        autoIncrement: true,
        field: "role_id", // SELECT role_id AS id
        primaryKey: true,
        type: DataTypes.INTEGER,
      ,
      name: DataTypes.STRING,
      description: DataTypes.STRING,
      createdAt: 
        type: DataTypes.DATE,
        field: "created_at",
      ,
      updatedAt: 
        type: DataTypes.DATE,
        field: "updated_at",
      ,
    ,
    
      sequelize,
      tableName: "roles",
      modelName: "Role",
    
  );

  return Role;
;

从 JavaScript 获取角色

controllers/roles.js

const models = require("../models");
const catchAsync = require("../middlewares/catchAsync");

exports.findAll = catchAsync(async (req, res) => 
  const roles = await models.Role.findAll();

  /*
  you can access 
    - role_id from db with roleId in JS
    - created_at from db with createdAt in JS
  */

  return res.status(200).json(
    status: "success",
    data: 
      roles,
    ,
  );
);

希望对您有所帮助!

【讨论】:

以上是关于Sequelize - 模型和迁移的主要内容,如果未能解决你的问题,请参考以下文章

sequelize 模型、迁移文件和外键。哪一个是对的?

在 Sequelize 中限制延迟加载的关联

使用随时间变化的模型为 Sequelize 制作可重现的迁移字符串?

如何从 Sequelize 模型自动生成迁移

NodeJS sequelize 自动生成模型并运行迁移 SQL 语法错误

我使用 Sequelize 的 DB 模型不进行迁移