如何在Sequelize CLI

时间:2017-09-22 05:37:39

标签: node.js sequelize.js psql sequelize-cli

我刚刚开始使用Sequelize和Sequelize CLI

由于这是一个开发时间,因此经常添加和删除列。将新列添加到现有模型的最佳方法是什么?

例如,我想要一个新列“已完成”到 Todo 模型。我将此列添加到models / todo.js。什么是下一步?

我尝试了sequelize db:migrate

无效:“未执行迁移,数据库架构已更新。”

7 个答案:

答案 0 :(得分:37)

如果您使用sequelize-cli,则需要先创建迁移。这只是一个文件,告诉引擎如何更新数据库以及如何在出现问题时回滚更改。您应该始终将此文件提交到存储库

$ sequelize migration:create --name name_of_your_migration

迁移文件如下所示:

module.exports = {
  up: function(queryInterface, Sequelize) {
    // logic for transforming into the new state
    return queryInterface.addColumn(
      'Todo',
      'completed',
     Sequelize.BOOLEAN
    );

  },

  down: function(queryInterface, Sequelize) {
    // logic for reverting the changes
    return queryInterface.removeColumn(
      'Todo',
      'completed'
    );
  }
}

然后,运行它:

$ sequelize db:migrate

答案 1 :(得分:4)

如果要将多个列添加到同一个表中,请将所有内容包装在Promise.all()中,然后将要添加的列放在数组中:

module.exports = {
  up: (queryInterface, Sequelize) => {
    return Promise.all([
      queryInterface.addColumn(
        'tableName',
        'columnName1',
        {
          type: Sequelize.STRING
        }
      ),
      queryInterface.addColumn(
        'tableName',
        'columnName2',
        {
          type: Sequelize.STRING
        }
      ),
    ]);
  },

  down: (queryInterface, Sequelize) => {
    return Promise.all([
      queryInterface.removeColumn('tableName', 'columnName1'),
      queryInterface.removeColumn('tableName', 'columnName2')
    ]);
  }
};

续列https://sequelize.readthedocs.io/en/2.0/api/datatypes/可以支持任何列类型

答案 2 :(得分:2)

要在序列中添加多列

步骤1:生成空迁移

sequelize migration:generate --name custom_name_describing_your_migration

第2步:将列添加到空迁移

根据文档https://sequelize.org/master/manual/migrations.html#migration-skeleton使用事务:

module.exports = {
    up: (queryInterface, Sequelize) => {
        return queryInterface.sequelize.transaction((t) => {
            return Promise.all([
                queryInterface.addColumn('table_name', 'field_one_name', {
                    type: Sequelize.STRING
                }, { transaction: t }),
                queryInterface.addColumn('table_name', 'field_two_name', {
                    type: Sequelize.STRING,
                }, { transaction: t })
            ])
        })
    },

    down: (queryInterface, Sequelize) => {
        return queryInterface.sequelize.transaction((t) => {
            return Promise.all([
                queryInterface.removeColumn('table_name', 'field_one_name', { transaction: t }),
                queryInterface.removeColumn('table_name', 'field_two_name', { transaction: t })
            ])
        })
    }
};

第3步:运行迁移

sequelize db:migrate

答案 3 :(得分:2)

您仍然可以使用带有对象参数的同步功能,该参数带有两个选项,当然是默认选项(不添加值)和实例(添加力或alter属性)。 因此,在这种情况下,您要使用UserModel.sync({ force: true }):这将创建表,如果表已经存在,则将其首先删除

UserModel.sync({ alter: true })

这将检查数据库中表的当前状态(它具有哪些列,它们的数据类型等),然后在表中执行必要的更改以使其与模式匹配... 使用模型实例时可以使用它 有关更新以及表和模型的更多信息,请查看有关更多功能的文档here

答案 4 :(得分:1)

每个Pter建议将Promise包装在事务中,这是一个使用async / await和事务的示例(来自创建索引时具有错误修复的文档):

'use strict';

module.exports = {
    async up(queryInterface, Sequelize) {
        const transaction = await queryInterface.sequelize.transaction();
        try {
            await queryInterface.addColumn(
                'Todo',
                'completed',
                {
                    type: Sequelize.STRING,
                },
                { transaction }
            );

            await queryInterface.addIndex(
                'Todo',
                {
                    fields: ['completed'],
                    unique: true,
                },
                { transaction }
            );

            await transaction.commit();
        } catch (err) {
            await transaction.rollback();
            throw err;
        }
    },

    async down(queryInterface, Sequelize) {
        const transaction = await queryInterface.sequelize.transaction();
        try {
            await queryInterface.removeColumn(
                'Todo',
                'completed',
                { transaction }
            );

            await transaction.commit();
        } catch (err) {
            await transaction.rollback();
            throw err;
        }
    }
};

答案 5 :(得分:0)

如果您使用的是vscode,则可以在迁移文件中添加类型定义。这有助于识别QueryInterface并序列化提供的所有方法。

 module.exports = {
/**
   * @typedef {import('sequelize').Sequelize} Sequelize
   * @typedef {import('sequelize').QueryInterface} QueryInterface
   */

  /**
   * @param {QueryInterface} queryInterface
   * @param {Sequelize} Sequelize
   * @returns
   */
  up: function(queryInterface, Sequelize) {
    // logic for transforming into the new state
    return queryInterface.addColumn(
      'Todo',
      'completed',
     Sequelize.BOOLEAN
    );

  },

  down: function(queryInterface, Sequelize) {
    // logic for reverting the changes
    return queryInterface.removeColumn(
      'Todo',
      'completed'
    );
  }
}

哪个将提供如下的智能感知 sequelize intellisense

答案 6 :(得分:0)

我认为,如果您在添加或删除列之前先检查特定表中的列,那就太好了。如果该列已经存在,这将消除错误。

'use strict';

module.exports = {
  // result_description
  up: async (queryInterface, Sequelize) => {
    let tableName = 'yourTableName';
    let columnName1 = 'columnName1';
    let columnName2 = 'columnName1';
    return Promise.all([
      queryInterface.describeTable(tableName)
        .then(tableDefinition => {
          if (tableDefinition.columnName1) return Promise.resolve();

          return queryInterface.addColumn(
            tableName,
            columnName1,
            {
              type: Sequelize.INTEGER,
              allowNull: false
            }
          );
        }),
      queryInterface.describeTable(tableName)
        .then(tableDefinition => {
          if (tableDefinition.columnName2) return Promise.resolve();

          return queryInterface.addColumn(
            tableName,
            columnName2,
            {
              type: Sequelize.STRING,
              allowNull: false
            }
          );
        })
    ]);
  },

  down: (queryInterface, Sequelize) => {

    let tableName = 'TestList';
    let columnName1 = 'totalScore';
    let columnName2 = 'resultDescription';
    return Promise.all([
      queryInterface.describeTable(tableName)
        .then(tableDefinition => {
          if (tableDefinition.columnName1) return Promise.resolve();
          return queryInterface.removeColumn(tableName, columnName1)
        }),
      queryInterface.describeTable(tableName)
        .then(tableDefinition => {
          if (tableDefinition.columnName1) return Promise.resolve();
          return queryInterface.removeColumn(tableName, columnName2)
        }),
    ]);
  }
};