Change Sequelize default foreign key with through tables

Nathaniel Babalola

I have two tables, apps and services. On services the PRIMARY KEY is set to field called orn. I created a through table between these two tables called apps_services with appId and serviceId

 appId: {
        type: Sequelize.UUID,
        references: {
          model: 'apps',
          key: 'id'
        }
      },

      serviceId: {
        type: Sequelize.STRING,
        references: {
          model: 'services',
          key: 'orn'
        }
      },

But here is a problem, when i use app.addService(foundService); (this creates a relationship between that app instance and foundService). When i used node debugger, i found out that sequelize tried inserting an id into serviceId instead of an orn

Executing (default): INSERT INTO "apps_services" ("id","appId","serviceId","createdAt","updatedAt") VALUES ('8d85f9b9-b472-4165-a345-657a0fe0d8ad','49f3daa4-1df4-4890-92f8-9a06f751ffb7','8cab340d-d11b-4e3b-842c-aeea9a28c368','2021-02-16 00:22:17.919 +00:00','2021-02-16 00:22:17.919 +00:00') RETURNING "id","appId","serviceId","userId","selfGranted","createdAt","updatedAt";

the third value in the bracket, the problem is id is not the foreignKey but orn is

below is the service table, we can see the orn column, which is the PRIMARY KEY and foreign key linking to the apps_services table.

Is there a way to force sequelize to use the orn field?

module.exports = (sequelize, DataTypes) => {
const apps_services = sequelize.define('apps_services', {
    id: {
        type: DataTypes.UUID,
        defaultValue: new DataTypes.UUIDV4(),
        unique: true,
        primaryKey: true
    },
    appId: {
        type: DataTypes.UUID,
    },

    serviceId: {
        type: DataTypes.STRING,
    },
    userId: {
        type: DataTypes.UUID
    },
    selfGranted: DataTypes.BOOLEAN
}, {
    timestamps: true
});

apps_services.associate = function (models) {
    models.apps.belongsToMany(models.services, {
        through: apps_services
    });

    models.services.belongsToMany(models.apps, {
        through: apps_services
    });
};
//apps_services.sync({alter: true});

return apps_services;

};

// this is apps_services migration

module.exports = {
up: async (queryInterface, Sequelize) => {
 await queryInterface.createTable('apps_services', {
   id:{
     type: Sequelize.UUID,
     defaultValue: new Sequelize.UUIDV4(),
     unique: true,
     primaryKey: true
 },
   appId: {
     type: Sequelize.UUID,
     references: {
       model: 'apps',
       key: 'id'
     }
   },

   serviceId: {
     type: Sequelize.STRING,
     references: {
       model: 'services',
       key: 'orn'
     }
   },

   userId: {
     type: Sequelize.UUID,
     references: {
       model: 'Users',
       key: 'id'
     }
   },

   createdAt: {
     allowNull: false,
     type: Sequelize.DATE
   },
   updatedAt: {
     allowNull: false,
     type: Sequelize.DATE
   },
   selfGranted: Sequelize.BOOLEAN,
 });
},

down: async (queryInterface, Sequelize) => {
 await queryInterface.dropTable('apps_services');
}
};

Below is the services table

we can see the orn there

Abhishek Shah

Yes you can mention which field to use from the opposite table.

apps_services.associate = function (models) {
    
    // you can move this association to apps model file
    models.apps.belongsToMany(models.services, {
        // Reference: https://sequelize.org/master/class/lib/model.js~Model.html#static-method-belongsToMany
        through: 'apps_services',
        foreignKey: 'appId', // <-- add this
    });
    
    // you can move this association to services model file
    models.services.belongsToMany(models.apps, {
        through: 'apps_services',
        foreignKey: 'serviceId', // <-- add this - name of field in through table
        otherKey: 'orn', // <-- add this - name of field in source table
    });
    
    /**
     * new relation below just to complete the Many to Many relation
     */
    // you can add this association in app_services model file
    models.apps_services.belongsTo(models.services, {
        // Reference: https://sequelize.org/master/class/lib/model.js~Model.html#static-method-belongsTo
        foreignKey: 'serviceId', // <--- name of field in source table
        targetKey: 'orn', // <--- name of field in target table
    });
    
    // you can add this association in app_services model file
    models.apps_services.belongsTo(models.apps, {
        foreignKey: 'appId', // <--- name of field in source table
        // targetKey: 'id', //(not needed as already primary key by default) <--- name of field in target table
    });

};

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related