Create|Add New Fields to Existing Sequelize Migration Model

Posted February 14, 2024
Create|Add New Fields to Existing Sequelize Migration Model

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:

Create|Add New Fields to Existing Sequelize Migration Model

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

Create|Add New Fields to Existing Sequelize Migration Model

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

Create|Add New Fields to Existing Sequelize Migration Model

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.

Create|Add New Fields to Existing Sequelize Migration Model

Written By:

Joseph Chege