问题
I've just started using Sequelize and Sequelize CLI
Since it's a development time, there are a frequent addition and deletion of columns. What the best the method to add a new column to an existing model?
For example, I want to a new column 'completed' to Todo model. I'll add this column to models/todo.js. Whats the next step?
I tried sequelize db:migrate
not working: "No migrations were executed, database schema was already up to date."
回答1:
If you are using sequelize-cli you need to create the migration first. This is just a file that tells the engine how to update the database and how to roll back the changes in case something goes wrong. You should always commit this file to your repository
$ sequelize migration:create --name name_of_your_migration
The migration file would look like this:
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'
);
}
}
And then, run it:
$ sequelize db:migrate
回答2:
If you want to add multiple columns to the same table, wrap everything in a Promise.all()
and put the columns you'd like to add within an array:
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')
]);
}
};
You can have any column type supported by sequelize https://sequelize.readthedocs.io/en/2.0/api/datatypes/
回答3:
If you are working in vscode, you can add type definition in the migration file. which helps to identify all the methods QueryInterface and sequelize provide.
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'
);
}
}
Which will provide intellisense like below
回答4:
To add multiple columns in sequelize
Step 1: generate empty migration
sequelize migration:generate --name custom_name_describing_your_migration
Step 2: add columns to the empty migration
Use a transaction as per the docs 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 })
])
})
}
};
Step 3: run the migration
sequelize db:migrate
回答5:
Per Pter suggestion to wrap Promise in a transaction, here's a sample using async/await and a transaction (from docs with bug fix when creating an index):
'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;
}
}
};
来源:https://stackoverflow.com/questions/46357533/how-to-add-delete-new-columns-in-sequelize-cli