Rodney Wormsbecher
Rodney Wormsbecher

Reputation: 927

Sequelize manytomany relationship doesn't create the relationship

I am using sequelize to create a database in my node.js project. Until now I was only using belongsTo and hasOne which worked flawlessly. However now that I need to create a many-to-many relationship, I am kinda puzzled that sequelize fails to interpret my belongsToMany with a "trough" property correctly. Any help would be appreciated. Cheers!

My index file which defines all relationship

const express = require('express');
const app = express();

const sequelize = require('./db/database');
const User = require('./models/User');
const Tenant = require('./models/Tenant');
const Role = require('./models/Role');
const Class = require('./models/Class');
const Level = require('./models/Level');
const Subject = require('./models/Subject');
const Student = require('./models/Student');
const Contact = require('./models/Contact');
const StudentContact = require('./models/StudentContact');

const userRoutes = require('./routes/user');
const authRoutes = require('./routes/auth');
const tenantRoutes = require('./routes/tenant');

const seed = require('./db/seed');

const port = process.env.PORT || 8080;

// allows node to parse querystrings
app.use(express.json({ extended: false }));

// routes for our endpoints
app.use('/api/auth', authRoutes);
app.use('/api/users', userRoutes);
app.use('/api/tenant', tenantRoutes);

// sets up the role and tenant relationships to the user.
User.belongsTo(Tenant, { foreignKey: { allowNull: false } });
User.belongsTo(Role, { foreignKey: { allowNull: false } });

Class.belongsTo(Level, { foreignKey: { allowNull: false } });
Class.belongsTo(Tenant, { foreignKey: { allowNull: false } });
Class.belongsTo(Subject, { foreignKey: { allowNull: false } });
Student.belongsTo(Class, { foreignKey: { allowNull: false } });

Student.belongsToMany(Contact, {
    as: 'Contacts',
    through: { model: StudentContact, unique: false },
    foreignKey: 'student_studentId'
});
Contact.belongsToMany(Student, {
    as: 'Students',
    through: { model: StudentContact, unique: false },
    foreignKey: 'contact_contactId'
});

sequelize
    .sync({ force: true })
    .then(result => {
        return Tenant.findByPk(1);
    })
    .then(tenant => {
        if (!tenant) {
            seed();
        }

        app.listen(port, () =>
            console.log(`Example app listening on port ${port}!`)
        );
    })
    .catch(err => console.log(err));

app.get('/', (req, res) => {
    sequelize
        .authenticate()
        .then(() => {
            res.send(`Hello World! Connection has been established successfully.`);
        })
        .catch(err => {
            res.send(`Hello World!  'Unable to connect to the database:' ${err}`);
        });
});

My Students Model:

const Sequelize = require('sequelize');
const sequelize = require('../db/database');

const Students = sequelize.define('student', {
    studentId: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
    }
});

module.exports = Students;

My contact model:

const Sequelize = require('sequelize');
const sequelize = require('../db/database');

const Contacts = sequelize.define('contact', {
    contactId: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
    }
});

module.exports = Contacts;

My StudentContact model:

const Sequelize = require('sequelize');
const sequelize = require('../db/database');

const StudentContact = sequelize.define('studentContact', {
    id: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
    }
});

module.exports = StudentContact;

The model it creates: enter image description here

I also tries setting the FK's manually but it also had no avail. The documentation of Sequelize only tells me to use BelongsToMany, but there clearly has to be more to it.

https://sequelize.org/master/class/lib/associations/belongs-to-many.js~BelongsToMany.html

Upvotes: 1

Views: 890

Answers (2)

Muzaffar Mahmood
Muzaffar Mahmood

Reputation: 1908

You just need to change definition of StudentContact like this:

const Sequelize = require('sequelize');
const sequelize = require('../db/database');

const StudentContact = sequelize.define('StudentContact',
    {
      id: {
        type: Sequelize.INTEGER,
        autoIncrement: true,
        allowNull: false,
        primaryKey: true
      },
      student_studentId: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      contact_contactId: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
    },
    {
      timestamps: false,
      tableName: 'StudentContact',
    }
  );

  StudentContact.associate = ({ Student, Contact }) => {
    ProductCategory.belongsTo(Student, {
      foreignKey: 'student_studentId',
    });
    ProductCategory.belongsTo(Contact, {
      foreignKey: 'contact_contactId',
    });
  };

module.exports = StudentContact;

Upvotes: 1

Osama
Osama

Reputation: 106

I had a similar problem a while back and was also very frustrated at not finding the right solution from sequelize docs. Later I worked around a solution which isn't the best but works fine for me. You can write the following two statements after manually setting both FK's in the StudentContact model.

StudentContact.belongsTo(Students, { foreignKey: "id" })

StudentContact.belongsTo(Contacts, { foreignKey: "id" });

Upvotes: 1

Related Questions