Create|Add New Fields to Existing Sequelize Migration Model
Posted February 14, 2024
Migrations in Sequelize are scripts that allow you to make changes to your database schema in a version-controlled and reversible way. You need to add new fields to an existing Sequelize migration and update the scripts.
If you have ready and working Sequelize Migrations, you might need to update the Migrations scripts. This way, you will get to add new fields/columns to your existing Sequelize migrations and the database. At the same time, you are trying to create a Sequelize migration from the existing model.
Now, Sequelize won’t give a direct ticket to update this existing migration. The good thing is the process is simple and Sequelize has command and functions to do exactly that. In this guide, you will learn how to add new fields and columns to an existing Sequelize migration model.
Step 1: Getting an Existing Sequelize Migration Model Ready
Before diving in, you need a working Sequelize migration. If not, check this Create|Generate|Run Sequelize CLI db Migrations with Node.js guide and get started right away.
Let’s assume you have the following Migrations script in your XXXXXXXXXXXXXX-create-todos.js
file:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
// TODO: Write migration to create the 'todos' table
await queryInterface.createTable('todos', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
completed: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
});
},
down: async (queryInterface, Sequelize) => {
// TODO: Write migration to drop the 'todos' table
await queryInterface.dropTable('todos');
}
};
At this point, I consider you have executed npx sequelize-cli db:migrate
command to apply the migration successfully.
Now, you want to add an extra field to this existing migration: So here you will add:
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
// New field name
description: {
type: Sequelize.TEXT
},
// New field name
priority: {
type: Sequelize.ENUM('low', 'medium', 'high'),
defaultValue: 'low'
},
completed: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
If you run npx sequelize-cli db:migrate
command again, Sequelize will tell you No migrations were executed, database schema was already up to date:
This is not Sequelize inability to apply these changes. It’s only that you are using the wrong approach. Let’s solve the puzzle
Step 2: Creating New Migrations on Top of the Existing Sequelize Migrations
Instead of removing the existing migration, run the Sequelize CLI command to create a new migration file. Make sure you are in the root directory of your project:
npx sequelize-cli migration:create --name modify_fields
npx sequelize migration:generate --name modify_fields
You will have a new migrations script, XXXXXXXXXXXXXX-create-modify_fields.js
. While keeping in Mind todos
table exists and it has new fields with data, you can’t run these migration to add new fields with createTable('todos')
Step 3: Updating the New Migration Model with the New Fields
Open the newly created migration XXXXXXXXXXXXXX-create-modify_fields.js
file. You need to define the up
and down
functions. However, this function won’t use createTable('todos')
and dropTable('todos')
.
In the up
function, tell Sequelize you have changes you want to make to the database schema. up
function will use addColumn('TableName', 'newField')
and down
will use removeColumn('TableName', 'newField')
syntax. TableName is the name of the table you want to modify and newField with the name of the new field you want to add:
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn('TableName', 'newField', {
type: Sequelize.STRING,
allowNull: false,
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn('TableName', 'newField');
}
};
In our case, we have these new fields:
// New field name
description: {
type: Sequelize.TEXT
},
// New field name
priority: {
type: Sequelize.ENUM('low', 'medium', 'high'),
defaultValue: 'low'
},
This means the complete XXXXXXXXXXXXXX-create-modify_fields.js
file should now look as follows:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
// Add new fields to the existing 'todos' table
await queryInterface.addColumn('todos', 'description', {
type: Sequelize.TEXT,
allowNull: true
});
await queryInterface.addColumn('todos', 'priority', {
type: Sequelize.ENUM('low', 'medium', 'high'),
defaultValue: 'low',
allowNull: true
});
},
down: async (queryInterface, Sequelize) => {
// Remove the newly added fields from the 'todos' table
await queryInterface.removeColumn('todos', 'description');
await queryInterface.removeColumn('todos', 'priority');
}
};
The same code can still be updated and use addColumn
in a single instance as follows:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
// Add new fields to the 'todos' table
await Promise.all([
queryInterface.addColumn(
'todos', // table name
'description', // new field name
{
type: Sequelize.TEXT,
allowNull: true,
},
),
queryInterface.addColumn(
'todos', // table name
'priority', // new field name
{
type: Sequelize.ENUM('low', 'medium', 'high'),
defaultValue: 'low',
},
),
]);
},
down: async (queryInterface, Sequelize) => {
// Remove added fields from the 'todos' table
await Promise.all([
queryInterface.removeColumn('todos', 'description'),
queryInterface.removeColumn('todos', 'priority'),
]);
},
};
Step 4: Running the New Migration on Top of The Existing Migration
The last step is to apply these changes. You just need to run your migration command:
npx sequelize-cli db:migrate
You should now verify that the database schema reflects the changes you made.
Conclusion
You’ve successfully added new fields to an existing Sequelize migration model. Consider checking this Creating Sequelize Migrations from an Existing Database to extend this Sequelize migrations guide.