一个迁移文件中的多个迁移语句

Multiple migration statements in one migration file

我正在尝试在单个迁移文件中执行多个迁移语句,以便一次性更改相同 table 的多个列。

我想知道我是不是以写的方式来做,还是有更好的更合适的方式来做:

迁移代码

module.exports = {
    up: function(queryInterface, Sequelize, done) {

        queryInterface.changeColumn('users', 'name', {
            type: Sequelize.STRING,
            allowNull: false,
            require: true,
            unique: true
        }).success(function() {
            queryInterface.changeColumn('users', 'address', {
                type: Sequelize.STRING,
                allowNull: false,
                require: true,
                unique: true
            }).success(function() {
                queryInterface.changeColumn('users', 'city', {
                    type: Sequelize.STRING,
                    allowNull: false,
                    require: true,
                    unique: true
                }).success(function() {
                    queryInterface.changeColumn('users', 'state', {
                        type: Sequelize.STRING,
                        allowNull: false,
                        require: true,
                        defaultValue: "ncjnbcb"
                    });
                    done();
                });
            });
        });
    }
};

但是我遇到了一个错误:

TypeError: undefined is not a function

由于我找不到任何调试迁移错误的方法,如果有人帮助我解决它会很棒,或者如果可能的话,告诉我们如何找出错误的方法迁移。

你的 TypeError 可能是因为你没有 returning 任何东西。 docs 说每个迁移函数都应该 return 一个 Promise。没有提到 done 回调。

为此,请尝试以下操作:

return Promise.all([
  queryInterface.changeColumn..., 
  queryInterface.changeColumn...
]);
module.exports = {
  up: async (queryInterface, Sequelize) => {
    try {
      await queryInterface.addColumn('User', 'name', {
        type: Sequelize.STRING
      });
      await queryInterface.addColumn('User', 'nickname', {
        type: Sequelize.STRING
      });
      return Promise.resolve();
    } catch (e) {
      return Promise.reject(e);
    }
  },

  down: async (queryInterface, Sequelize) => {
    try {
      await queryInterface.removeColumn('Challenges', 'name');
      await queryInterface.removeColumn('Challenges', 'nickname');
      return Promise.resolve();
    } catch (e) {
      return Promise.reject(e);
    }
  }
};

Promise.all用于事务(更安全的迁移):

module.exports = {
  up: async (queryInterface, Sequelize) => {
    return queryInterface.sequelize.transaction(t => {
      return Promise.all([
        queryInterface.changeColumn('users', 'name', 
          { type: Sequelize.STRING },
          { transaction: t }
        ),
        queryInterface.changeColumn('users', 'address', 
          { type: Sequelize.STRING },
          { transaction: t }
        ),
        queryInterface.changeColumn('users', 'city', 
          { type: Sequelize.STRING },
          { transaction: t }
        )
      ]);
    });
  },

  down: async (queryInterface, Sequelize) => {
    return queryInterface.sequelize.transaction((t) => {
      return Promise.all([
        queryInterface.removeColumn('users', 'name', { transaction: t }),
        queryInterface.removeColumn('users', 'address', { transaction: t }),
        queryInterface.removeColumn('users', 'city', { transaction: t })
      ])
    })
  }
};

如果某些查询被拒绝,在没有事务的情况下使用 Promise.all 会导致问题。使用事务是安全的,这样所有操作都会成功执行,或者会进行 none 的更改。

所以这是 2 个答案的组合。

@Firmino Changani - 效果很好但会完成一些迁移,即使有些迁移失败

@Aswin Sanakan - 表示它们都可以工作或 none 迁移,但如果第二次迁移依赖于第一次,它将无法工作

我正在创建一个 table 并向该 table 添加一个特殊索引。所以我最终将它们结合起来,以下对我有用:

'use strict';
module.exports = {
  up: async (queryInterface, Sequelize) => {
    return queryInterface.sequelize.transaction(async t => {
      try {
        await queryInterface.createTable(
          'phonenumbers',
          {
            id: {
              allowNull: false,
              autoIncrement: true,
              primaryKey: true,
              type: Sequelize.INTEGER
            },
            full_number: {
              type: Sequelize.STRING,
              unique: true
            },
            phone: {
              type: Sequelize.STRING
            },
            extension: {
              type: Sequelize.INTEGER,
            },
            country_id: {
              type: Sequelize.INTEGER
            },
            is_valid_format: {
              type: Sequelize.BOOLEAN
            },
            type: {
              type: Sequelize.STRING
            },
            createdAt: {
              allowNull: false,
              type: Sequelize.DATE
            },
            updatedAt: {
              allowNull: false,
              type: Sequelize.DATE
            },
          },
          { transaction: t }
        ),
        await queryInterface.addIndex(
          'phonenumbers',
          ['phone'],
          {
            name: 'constraint-phone-extension',
            where: {extension: null},
            transaction: t
          }
        )
        return Promise.resolve();
      } catch (e) {
        return Promise.reject(e);
      }
    });
  },
  down: async (queryInterface, Sequelize) => {
    return queryInterface.sequelize.transaction(async t => {
      try {
        await queryInterface.dropTable('phonenumbers', { transaction: t }),
        return Promise.resolve();
      } catch (e) {
        return Promise.reject(e);
      }
    })
  }
};