Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating associations in Sequelize migration

Nodejs. Sequelize 4.41. Try to make 2 models with relation many-to-many through another table. Running with sequelize-cli, for example...

sequelize model:generate --name Camera --attributes name:string,sn:string

Here is models

// Camera model

'use strict';

module.exports = (sequelize, DataTypes) => {
  const Сamera = sequelize.define('Сamera', {
    name: DataTypes.STRING,
    sn: DataTypes.STRING
  }, {});
  Сamera.associate = function(models) {
    // associations can be defined here
      Camera.belongsToMany(models.Relay, {through: 'CameraRelay'});
  };
  return Сamera;
};

And

// Relay model

'use strict';

module.exports = (sequelize, DataTypes) => {
  const Relay = sequelize.define('Relay', {
    name: DataTypes.STRING,
    sn: DataTypes.STRING,
    channel: DataTypes.INTEGER
  }, {});
  Relay.associate = function(models) {
    // associations can be defined here
      Relay.belongsToMany(models.Camera, {through: 'CameraRelay'});
  };
  return Relay;
};

In documentation there are phrase

Belongs-To-Many associations are used to connect sources with multiple targets. Furthermore the targets can also have connections to multiple sources.

Project.belongsToMany(User, {through: 'UserProject'}); User.belongsToMany(Project, {through: 'UserProject'});

This will create a new model called UserProject with the equivalent foreign keys projectId and userId.

Migrations is

// create-relay

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Relays', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        type: Sequelize.STRING
      },
      sn: {
        type: Sequelize.STRING
      },
      channel: {
        type: Sequelize.INTEGER
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Relays');
  }
};

And

//create camera
'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Сameras', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        type: Sequelize.STRING
      },
      sn: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Сameras');
  }
};

Why it doesn't create model CameraRelay and doesn't create migration for same model when I running migrate?

like image 705
Evgeny Gil Avatar asked Jan 28 '23 04:01

Evgeny Gil


1 Answers

I guess the misunderstanding is about sync vs migration: great part of documentation you are referring to, is using the sync method to create all tables and associations starting from models.

When you are using migrations, you are creating db all of your table/columns/associations using migration files (and in my hopinion, this is a better way for something that is going to production).

To understand the difference, just look at your camera model vs your camera migration file:

  • the model has only name and sn properties defined
  • the migration file has of course name and sn, but it has id, createdAt and updatedAt too.

Migrations are file with the aim of change your db in a safe way, allowing you to rollback to any point in the past.

So, back to your problem, you have to:

  • create a new migration file to create your new CameraRelay table, with foreign keys to both Camera and Relay tables
  • update your current Camera migration file with one-to-many relation to CameraRelay table
  • update your current Relay migration file with one-to-many relation to CameraRelay table

CameraRelay migration example:

    'use strict';
    module.exports = {
      up: (queryInterface, Sequelize) => {
        return queryInterface.createTable('CameraRelays', {
          cameraId: {
            primaryKey: true,
            type: Sequelize.INTEGER,
            allowNull: false,
            references: {        
              model: 'Relay',
              key: 'id'
            }
          },
          relayId: {
            primaryKey: true,
            type: Sequelize.INTEGER,
            allowNull: false,
            references: {         
              model: 'Camera',
              key: 'id'
            }
          },
          createdAt: {
            allowNull: false,
            type: Sequelize.DATE
          },
          updatedAt: {
            allowNull: false,
            type: Sequelize.DATE
          }
        });
      },
      down: (queryInterface, Sequelize) => {
        return queryInterface.dropTable('CameraRelays');
      }
    };

like image 88
napcoder Avatar answered Jan 31 '23 22:01

napcoder