khukho
khukho

Reputation: 476

Association in Sequelize

I'm trying to get data like below:

"data": {
    "religions": {
        "Major1Name": {
            "AttendanceYear1Name": {
                "student": [ {...}, {...}, {...} ]
            },
            "AttendanceYear2Name": {
                "student": [ {...}, {...}, {...} ]
            }
        },
        "Major2Name": {
            "AttendanceYear1Name": {
                "student": [ {...}, {...}, {...} ]
            },
            "AttendanceYear2Name": {
                "student": [ {...}, {...}, {...} ]
            }
        }
    }
}

I know how to set up a basic level of associations for eg. student and major. But in my database knowledge, I have no idea how to associate with religions and majors, and also in Sequelize. Please help.

I have the followings tables:

  1. majors
  2. attendance_years
  3. religions
  4. students
  5. enrollments

Below is my models.

majors

'use strict';

const { Model } = require('sequelize');

module.exports = (sequelize, DataTypes) => {
  class Major extends Model {
    static associate(models) {
      Major.hasMany(models.Enrollment, {
        foreignKey: 'majorId',
        as: 'major',
      });
    }
  }

  Major.init(
    {
      majorId: {
        allowNull: false,
        autoIncrement: true,
        field: 'major_id',
        primaryKey: true,
        type: DataTypes.INTEGER,
      },
    { ... }
    },
    {
      sequelize,
      modelName: 'Major',
      tableName: 'majors',
    }
  );

  return Major;
};

attendance_years

"use strict";

const { Model } = require("sequelize");

module.exports = (sequelize, DataTypes) => {
  class AttendanceYear extends Model {
    static associate(models) {
      AttendanceYear.hasMany(models.Enrollment, {
        as: "enrollments",
        foreignKey: "attendance_year_id",
      });
    }
  }

  AttendanceYear.init(
    {
      attendanceYearId: {
        allowNull: false,
        autoIncrement: true,
        field: "attendance_year_id",
        primaryKey: true,
        type: DataTypes.INTEGER,
      },
    { ... }
    },
    {
      sequelize,
      modelName: "AttendanceYear",
      tableName: "attendance_years",
    }
  );

  return AttendanceYear;
};

religions

"use strict";

const { Model } = require("sequelize");

module.exports = (sequelize, DataTypes) => {
  class Religion extends Model {
    static associate(models) {
      Religion.hasMany(models.Student, {
        foreignKey: "religionId",
        as: "student",
      });
    }
  }

  Religion.init(
    {
      religionId: {
        allowNull: false,
        autoIncrement: true,
        field: "religion_id",
        primaryKey: true,
        type: DataTypes.INTEGER,
      },
      { ... }
    },
    {
      sequelize,
      modelName: "Religion",
      tableName: "religions",
    }
  );

  return Religion;
};

students

'use strict';

const { Model } = require('sequelize');

module.exports = (sequelize, DataTypes) => {
  class Student extends Model {
    static associate(models) {

      Student.belongsTo(models.Religion, {
        foreignKey: 'religionId',
        as: 'religion',
        targetKey: 'religionId',
      });

      Student.belongsTo(models.Enrollment, {
        foreignKey: 'studentId',
        as: 'enrollment',
      });
    }
  }

  Student.init(
    {
      studentId: {
        allowNull: false,
        autoIncrement: true,
        field: 'student_id',
        primaryKey: true,
        type: DataTypes.INTEGER,
      },
      name: {
        allowNull: false,
        field: 'name_en',
        type: DataTypes.STRING(50),
      },
      religionId: {
        allowNull: false,
        field: 'religion_id',
        references: {
          model: 'religons',
          key: 'religion_id',
        },
        type: DataTypes.INTEGER,
      },
    },
    {
      sequelize,
      modelName: 'Student',
      tableName: 'students',
    }
  );
  return Student;
};

and enrollments

'use strict';

const { Model } = require('sequelize');

module.exports = (sequelize, DataTypes) => {
  class Enrollment extends Model {
    static associate(models) {

      Enrollment.belongsTo(models.Major, {
        foreignKey: 'majorId',
        as: 'major',
      });

      Enrollment.belongsTo(models.Student, {
        foreignKey: 'studentId',
        as: 'student',
      });

      Enrollment.belongsTo(models.AttendanceYear, {
        foreignKey: 'attendanceYearId',
        as: 'attendanceYear',
      });
    }
  }

  Enrollment.init(
    {
      enrollmentId: {
        allowNull: false,
        autoIncrement: true,
        field: 'enrollment_id',
        primaryKey: true,
        type: DataTypes.INTEGER,
      },
      majorId: {
        allowNull: false,
        field: 'major_id',
        onDelete: 'NO ACTION',
        onUpdate: 'CASCADE',
        references: {
          model: 'majors',
          key: 'major_id',
        },
        type: DataTypes.INTEGER,
      },
      studentId: {
        allowNull: false,
        field: 'student_id',
        onDelete: 'CASCADE',
        onUpdate: 'CASCADE',
        references: {
          model: 'students',
          key: 'student_id',
        },
        type: DataTypes.INTEGER,
      },
      attendanceYearId: {
        allowNull: false,
        field: 'attendance_year_id',
        onDelete: 'NO ACTION',
        onUpdate: 'CASCADE',
        references: {
          model: 'attendance_years',
          key: 'attendance_year_id',
        },
        type: DataTypes.INTEGER,
      },
    },
    {
      sequelize,
      modelName: 'Enrollment',
      tableName: 'enrollments',
    }
  );

  return Enrollment;
};

What I've done and doesn't work

const religions = await models.Religion.findAll({
    where: { religionId: req.params.religionId },
    include: [
      {
        model: models.Major,
        as: 'major',
        include: [
          {
            model: models.AttendanceYear,
            as: 'attendanceYear',
            include: [
              {
                model: models.Student,
                as: 'student',
                attributes: ['studentId', 'nameMm', 'nameEn', 'nrc'],
                include: [
                  {
                    model: models.Parent,
                    as: 'parent',
                    attributes: ['fatherNameMm', 'fatherNameEn', 'fatherNrc'],
                  },
                  {
                    model: models.Enrollment,
                    as: 'enrollment',
                    attributes: ['rollNo'],
                    where: {
                      academicYearId: req.params.academicYearId,
                    },
                  },
                ],
              },
            ],
          },
        ],
      },
    ],
  });

Error

SequelizeEagerLoadingError: Major is not associated to Religion!

Updated

I have the followings models (which will be the tables in the database) files in this structure src/database/models/:

  1. majors
  2. attendance_years
  3. religions
  4. students
  5. enrollments

The whold structure is:

database/migrations/....js
database/models/....js
database/seeders/....js

I have an index.js file inside that models/ directory and it is like below:

'use strict';

const config = require('../../config/config');
const fs = require('fs');
const path = require('path');
const { Sequelize, DataTypes } = require('sequelize');
const basename = path.basename(__filename);
const db = {};

const logger = require('../../startup/logger')();

const ENV = config[process.env.NODE_ENV];

let sequelize;
sequelize = new Sequelize(ENV.database, ENV.username, ENV.password, {
  dialect: 'mysql',
  host: ENV.host,
  define: {
    charset: 'utf8',
    collate: 'utf8_general_ci',
    timestamps: false, // omit createdAt and updatedAt
  },
});

sequelize
  .authenticate()
  .then(() => {
    // logger.info('Connected to the database.');
    console.log('Connected to the database.');
  })
  .catch((error) => {
    logger.error('Unable to connect to the database.', error);
    console.log(`Unable to connect to the database.`, error);
    process.exit(1);
  });

fs.readdirSync(__dirname)
  .filter((file) => {
    return (
      file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'
    );
  })
  .forEach((file) => {
    const model = require(path.join(__dirname, file))(sequelize, DataTypes);
    db[model.name] = model;
  });

db.sequelize = sequelize;
db.Sequelize = Sequelize;

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

module.exports = db;

With that implementation, I don't need to import the required models inside the model files and also route handlers and just need the following line.

const models = require('../database/models');
/** I can easily get model instance by calling models.Student to get Student model. **/

And the reason that I don't use the sync approach is that I'm afraid to accidentally lose my data in the production if I update the models or add a new one. Therefore, I used sequelize-cli. With it, I can turn my models into tables by running sequelize db:migrate.

The reason that I have explicitly defined the attribute and table name is that I want them to follow the MySQL naming conventions: attendance_years and attendance_year_id for instance. But when I run the calls to the database, I see lots of naming aliases in the terminal: attendance_year_id as attendanceYearId etc. I think this might impact the querying performance and so, I will consider letting sequelize completely manage the naming conventions.

Upvotes: 1

Views: 2946

Answers (2)

Bankole Alex-Esan
Bankole Alex-Esan

Reputation: 58

Thanks for reaching out to me on Twitter. I really appreciate it. That being said, let's see if we can go about answering your question. Please allow me to geek out a bit before getting to the solution I wish to provide.

First, some advice from my personal experience.

  1. Sequelize is very powerful. And under the hood it solves a lot of problems for you, meaning you don't have to worry about a lot of things like Primary key attributes, Foreign key column names, table names etc. Outside of some really complex associations or in some edge cases (like if you're working with a legacy database, for instance), you really don't have to explicitly declare what those are, but rather let sequelize do the heavy lifting for you. I mention this because I noticed you tried specifing primaryKey attributes and included the tableName attribute in the options object of your model definitions, which is okay, but really unnecessary, and could in fact actually interfere with the sequelize engines' queries in which case you may have to define these attributes everywhere and that's just a mess. Sequelize generates primaryKey attributes and tableNames by default - so, if you can, please minimize unnecessary definitions as much as possible - See why from the docs on table name inference here. If you do feel the need to have your own custom key for models, consider using a UUID attribute, like so.
// Custom UUID attribute seperate from the model id but also generated by sequelize.
studentUUID: {
  type: DataTypes.UUID,
  defaultValue: Sequelize.UUIDV4 // will generate a UUID for every created instance
}

That saves you both the trouble of having to uniquely name primaryKey fields, as well as preventing situations where keys may have similar values. It also gives you an extra unique attribute to use in your queries to ensure you get a single record.

  1. I also noticed you tried defining the model associations in static methods in the model definitions. I'm not sure why you did this, but I don't think that's how associations are defined, both from my experience and the official sequelize docs (Version 6 - as seen here). Rather, how it's done is that associations are defined in the model file after the model has been initialized, before exporting - e.g.
const { Model, Sequelize, Datatypes } = require('sequelize');
const db = require('../path/to/sequelizeConnectionInstance');

// Let's say we want to associate Religion model to Major model in a 1 - N relationship;
// To do that, we import the Major model 
const Major = require('./Major'); 

class Religion extends Model { /* Yes, it's an empty object and that's okay */ }

Religion.init({
  // Model attributes are defined here
  name: {
    type: DataTypes.STRING,
    allowNull: false
  },
  founder: {
    type: DataTypes.STRING
    // allowNull defaults to true
  }, 
  {...}
}, {
  // Other model options go here, but you rarely need more than the following 2
  sequelize: db, // We need to pass the connection instance
  modelName: 'religion' // I use small letters to avoid ambiguity. you'll see why in a bit
  // No table name attribute is required. the table "religions" is automatically created
});

// The relationship(s) is/are then defined below
Religion.hasMany(Major);
Major.belongsTo(Religion); // The Major model must have a religionId attribute
/* 
*  Sequelize will automagically associate Major to Religion even without the FK being   
*  explicitly described in the association. What sequelize does is find the `modelName+id` 
*  attribute in the associated model. i.e. if `Foo.hasMany(Bar)` and `Bar.belongsTo(Foo)`, *  sequelize will look for the `FooId` property in the Bar model, unless you specifiy 
*  otherwise. Also, the convention I use (and what I've found to work) is to import 
*  'child' models to 'parent' model definitions to make 
*  associations.
*/
// THEN we export the model 
modules.export = Religion;

Also worth keeping in mind is that, when you associate model entities, sequelize will automatically pluralize the name of the entity in the results, depending on the relationship (i.e. if the parent entity hasMany of the child entity), and returns the results as an array. e.g. if Religion.hasMany(Major), the result will return religion.majors = [/*an array of majors*/].

  1. From the above example, you can begin to see some changes that may fix your problem right off the bat. But one last thing I feel to mention before proposing my solution. Again, not unrelated to the previous point, I notice you tried specifying references on some attributes. You don't need to do this. That's kind of a NoSQL thing. It's sufficient enough to define the attribute and it's type only, and when the association is made, sequelize will figure out the foreign key. You can also specify other details in the association. So for instance; Assuming a 1 - N relationship between Religion and Major models -

in Major.js model file you can specify the religion FK like this

class Major extends Model {}
Major.init(
  {
     religionId: {
        type: Datatypes.INTEGER, 
        allowNull: true, // set to false if the value is compulsory
        // that's all folks. no other details required.
     }, 
     {/* ...otherAttributes */}
  }, 
  {/* ...options, etc */}
)

module.exports = Major;

Then in Religion.js

const Major = require('./Major');
Religion.init(
  {
// just declare religions OWN attributes as usual  
     {/* ...religionObjectAttributes */}
  }, 
  {/* ...options, etc */}
)
Religion.hasMany(Major, {
  foreignKey: 'religionId',
  onDelete: 'NO ACTION', // what happens when you delete Major ? 
  onUpdate: 'CASCADE',
})

Major.belongsTo(Religion, {
  foreignKey: 'religionId',
})

module.exports = Religion;

As a side note, you very often don't have to include the onDelete and onUpdate attributes in the association, as the defaults are well suited for most use cases. Also worth noting, you can have multiple relationships, in which case you can use aliases. But that doesn't seem to be necessary or relevant to your question (at least from the onset), but still worth noting and very useful.

That being said. Now to your question: (possible solution 1 - The Easy Way)

The very first thing you need to do is define exactly what the structure of the relationships between the Entities will be like. From the data object, it appears to me to be something like

  • Religion to Major: 1 to N (One religion has Many Majors)
  • Major to AttendanceYear: 1 to N (One Major has Many attendance years)
  • AttendanceYear to Student: 1 to N (One Attendance Year has many students) thus, I imagine your desired sequelize response to be something like this:
religions: [ // array of religions since your'e fetching multiple
  {
     id: 1, // the religion Id
     name: string, // name of religion or whatever
     /*... any other religion attributes */
     majors: [ // array since each religion has multiple majors
        {
           id: 1, // the major Id 
           name: string, // the name of the major or whatever
           /*... any other major attributes */
           attendanceYears: [ // array since each major has multipl
              {
                  id: 1, // the first attendanceYear id
                  name: string, // name of first attendanceYear
                   /*... any other attendanceYear attributes */
                  students: [ // array since ...
                      {
                         id: 1, // student id
                         name: string, // student name
                         /*... any other student attributes */
                      },
                      {
                         id: 2, // id of second student
                         name: string, // 2nd student name
                          /*... any other student attributes */
                      }, 
                      {
                         id: 3, // id of 3rd student
                         name: string, // 3rd student name
                          /*... any other student attributes */
                      }, 
                  ]
              }, 
              {
                  id: 2, // the second attendanceYear id
                  name: string, // name of second attendanceYear
                   /*... other attributes of 2nd attendance year */
                  students: [
                      {
                         id: 4, // student id
                         name: string, // student name
                         /*... any other student attributes */
                      },
                      {
                         id: 5, // id of second student
                         name: string, // 2nd student name
                          /*... any other student attributes */
                      }, 
                      {
                         id: 6, // id of 3rd student
                         name: string, // 3rd student name
                          /*... any other student attributes */
                      }, 
                  ]
              }
           ]
        }, 
        {/*... this is another major instance in majors array */}
     ]
  }, 
  {/*... this is another religion instance in religions array*/}
]

Okay. I'm not sure if this is what you're going for, but going off of the example you gave, that's what I'm working with. For the code, first, some configurations that will help you down the line

  1. save the sequelize db connection instance in a seperate file. I'm calling it db.js
const { Sequelize } = require('sequelize');

module.exports = new Sequelize('dbName', 'dbUsername', 'dbPassword', {
  host: 'localhost',
  dialect: 'mysql', // or whatever dialect you're using
});

I'm putting this here now, just so it's clear what I'm referring to when using the db variable elsewhere. Then we create the models Religion.js

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
// import any models to associate
const Student = require('./Student'); 

class Religion extends Model {}
Religion.init(
   {
     /* religion only attrs, let sequelize generate id*/
   }, 
   {
      sequelize: db, 
      modelName: 'religion'
   }
)
// make association
Religion.hasMany(Student);
Student.belongsTo(Religion);
module.exports = Religion;

Major.js

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
// import any models to associate
const Enrollment = require('./Enrollment');
class Major extends Model {}

Major.init(
   {
      /* major only attrs, let sequelize generate id*/
   }, 
   {
      sequelize: db, 
      modelName: 'major'
   }
)
Major.hasMany(Enrollment)
Enrollment.belongsTo(Major);
module.exports = Major;

Student.js

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
const Enrollment = require('./Enrollment');
class Student extends Model {}

Student.init(
   {
      religionId: {
          type: DataTypes.INTEGER,
      },
      /* other student attrs, let sequelize generate id attr */
   }, 
   {
      sequelize: db, 
      modelName: 'student'
   }
)
Student.hasMany(Enrollment);
Enrollment.belongsTo(Student);
module.exports = Student;

Enrollment.js

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
class Enrollment extends Model {}

Enrollment.init(
   {
      attendanceYearId: {
          type: DataTypes.INTEGER,  // FK for attendanceYear
      }, 
      studentId: {
          type: DataTypes.INTEGER, // FK for student
      }, 
      majorId: {
          type: DataTypes.INTEGER, // FK for major
      },
      /* other 'Major' attrs, let sequelize generate id attr */
   }, 
   {
      sequelize: db, 
      modelName: 'enrollment'
   }
)
module.exports = Enrollment;

AttendanceYear.js

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
const Enrollment = require('./Enrollment');
class AttendanceYear extends Model {}

AttendanceYear.init(
   {
      /* attendanceYear attrs, let sequelize generate id attr */
   }, 
   {
      sequelize: db, 
      modelName: 'attendanceYear'
   }
)

AttendanceYear.hasMany(Enrollment);
Enrollment.belongsTo(AttendanceYear);
module.exports = AttendanceYear;

And with that, all your entities are setup to get the data in the that shape you requested. e.g. (using in a function)

someOtherFile.js

// First import all the models you may wish to use i.e. 
const db = require('../path/to/db.js');
const Religion = require('../path/to/models/Religion');
const Major = require('../path/to/models/Major');
const AttendanceYear = require('../path/to/models/AttendanceYear');
const Student = require('../path/to/models/Student');
const Enrollment = require('../path/to/models/Enrollment');

// Uncomment the line below to update db structure if model changes are made
// db.sync({alter: true}) 

/* query function starts here */
const religions = await Religion.findAndCountAll({
   // If you want all religions then you don't need a where object
   // Also "where: {id: someValue}" should get only 1 result
   include: [{model: Major, include: [{ model: Enrollment, include:[AttendanceYear, Student]}]}]
})

Worth noting, if you're going to search for something using it's primary key, then the .findByPK(idValueOrVariable) is much better for that, and you can also pass in includes and other options etc. That being said, Hopefully this sheds some light on how sequelize works and how you can approach the problem; However, I get the feeling that this isn't what you're going for, and if not, then this at least lays the ground work for the 2nd solution I'm proposing.

Possible Solution 2: Restructuring

The 2nd solution, in my opinion, is one that I believe more closely addresses the problem. from your model definitions (and giving it a little thought) it appears that it should be -
  • each Major has many Enrollments and vice versa, N - N (because a student may have multiple majors in the same enrollment)
  • each AttendanceYear has many Enrollments, 1 - N
  • each Religion has many Students, 1 - N,
  • each Student can have many Enrollments (and by extension, Majors), 1 - N Thus first step would then be, imho, figuring out which is 'parent' to which, to know how and where to make the right associations. However, this will fundamentally change the way your reponse json will be shaped, seeing as there's no direct relationships between some entities (for instance, Religion is not directly related to Major in any way except through Student -> Enrollment -> then Major). So the response would be something like religions[i].students[i].enrollments[i].majors[i]. And in that case, to directly sort Majors in order of Religions would be something you would do after getting all the religions and their nested objects, and mapping Majors by Students and sorting them however you want. As far as I know, there's no single query (or combination of nested queries) that can do this for you in an SQL db without a direct (or even an indirect) Foreign Key - Spoiler alert, this is where the sequelize error is coming from.

However, there is a way

. Drum roll please... "Through" Tables. i.e. intermediate/junction tables that act as relational tables between Models. Though generally used for N - N relationships, they can also be used in situations like this to create associations where none might have previously existed, by creating Junction tables. Worth noting however, are the intricacies that come with using through/junction tables - See the docs on that here

Overall, I think the most effective way to model the database would be something like this

Image Showing DB Design

So, how would we do this? We need to create "through" models for enrollment to major, major to attendance, and religion to major. *** Update *** The "through" models will looks something like this:

ReligionMajors

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
// import any models to associate
const Religion = require('./Religion');
const Major = require('./Major');

class ReligionMajors extends Model {}
ReligionMajors.init({
  religionId: {
    type: DataTypes.INTEGER,
    references: {  // You don't need to include this, just showing for reference 
      model: Religion,
      key: 'id'
    }
  },
  majorId: {
    type: DataTypes.INTEGER,
    references: {  // again you don't need this, just showing for reference
      model: Major,
      key: 'id'
    }
  }
});
Religion.belongsToMany(Major, { through: ReligionMajors });
Major.belongsToMany(Religion, { through: ReligionMajors});

EnrollmentMajors

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
// import any models to associate
const Enrollment = require('./Enrollment');
const Major = require('./Major');

class EnrollmentMajors extends Model {}
EnrollmentMajors.init({
  enrolmentId: {
    type: DataTypes.INTEGER,
  },
  majorId: {
    type: DataTypes.INTEGER,
  }
});
Enrollment.belongsToMany(Major, { through: EnrollmentMajors });
Major.belongsToMany(Enrollment, { through: EnrollmentMajors});

AttendanceYearMajors

const { Model, Sequelize, DataTypes } = require('sequelize');
const db = require('../path/to/db.js');
// import any models to associate
const AttendanceYear = require('./AttendanceYear');
const Major = require('./Major');

class AttendanceYearMajors extends Model {}
AttendanceYearMajors.init({
  attendanceYearId: {
    type: DataTypes.INTEGER,
  },
  majorId: {
    type: DataTypes.INTEGER,
  }
});
AttendanceYear.belongsToMany(Major, { through: AttendanceYearMajors });
Major.belongsToMany(AttendanceYear, { through: AttendanceYearMajors});

The tricky part with this is that you may have to start thinking about when and how you want to make these associations on a record. Also, this changes the relationship between the Major and Enrollments models to a many to many relationship, but that's okay.

What we can now do, like I said before, is figure out when and how to create records in the 'through' models to create the associations we need.

One way to do the Religion to Major association would be to, basically perform a series of steps with the data you have i.e.

const db = require('../path/to/db.js');
const Enrollment = require('../path/to/model/Enrollment');
const Major = require('../path/to/model/Major');
const Student = require('../path/to/model/Student');
const Religion = require('../path/to/model/Religion');
const EnrollmentMajors = require('../path/to/model/EnrollmentMajors');
const ReligionMajors = require('../path/to/model/ReligionMajors');
try{
   const studentEnrollment = await Enrollment.create(
      {
         studentId: studentIdFromReq,
         attendanceYearId: attendanceYearIdFromRequest,
      }
   );
   if(studenEnrollment){
      // associate the Enrollment with the Major if you have the Major id
      const studentEnrolledMajor = await EnrollmentMajors.create(
         {
             enrollmentId: studentEnrollment.id,
             majorId: majorId
         }
      )
      // Then, get the students' Religion Id, and associate with Major
      const studentWithReligion = await Student.findByPK(studentIdFromReq, 
         {include: [Religion]}
      )
      const religionMajorAssociation = await ReligionMajors.findOrCreate( 
         {
            religionId: studentWithReligion.religion.id, // or student.religionId
            majorId: majorId
         }
      )
      /* we use findOrCreate to avoid making duplicate religion-major assocs */
      if(religionMajorAssociation){
         // The association was created successfully, so you can do whatever else
      }
   }
} catch(err){
   console.log(err)
}

Notice I put the code in a try-catch block. This is good practice generally, so you can easily see whatever errors sequelize might throw (if any)...

Upvotes: 2

Anatoly
Anatoly

Reputation: 22758

You need to define an association in religions file like this next to the Religion.hasMany(models.Student association:

 Religion.hasMany(models.Major, {
        foreignKey: "religionId",
        as: "major",
      });

Upvotes: 2

Related Questions