Basant Singh
Basant Singh

Reputation: 5916

Sequelize.js many to many eager loading

I have 2 models: User and Team

There are multiple kinds of users (in this case Mentors and Moderators) which are differentiated using an attribute in the User model(). The associations between User and Team are as below:

User.hasMany(models.Team, {as: 'Mentors', through: models.TeamMentor, foreignKey: 'mentorId'});
User.hasMany(models.Team, {as: 'Moderators', through: models.TeamModerator, foreignKey: 'moderatorId'});


Team.hasMany(models.User, {through: models.TeamMentor, foreignKey: 'teamId'});
Team.hasMany(models.User, {through: models.TeamModerator, foreignKey: 'teamId'});

Now I am trying to get the details of the team along with separate objects for all the mentors and moderators that are assigned to the teams. I came to know about the getters and setters for many to many relationships from the documentation but I am not sure how to use the method since there are two different kinds of associations between two models here:

  1. Team - Mentor (User)
  2. Team - Moderator (User)

How to correctly query for a team's details in this case?

PS: TeamMentor and TeamModerator are empty models to help the many to many joins

Upvotes: 3

Views: 3786

Answers (1)

st.never
st.never

Reputation: 11753

I'm assuming you have N:M relationships between all those models? Like this:

User ---mentors many---> Teams
User --moderates many--> Teams

Team --is moderated by many--> Users
Team --is mentored by many---> Users

If so, you might want to use the as option not only in the User.hasMany(Team) that you already have, but also in the Team.hasMany(User):

Team.hasMany(models.User, {as: 'mentors', through: models.TeamMentor, foreignKey: 'teamId'});
Team.hasMany(models.User, {as: 'moderators', through: models.TeamModerator, foreignKey: 'teamId'});

I think you can then eager load some or all of them during a query like so:

Team.findAll({
  where: {...},
  include: [
    {model: User, as: `moderators` },
    {model: User, as: `mentors` }

    // or just use this to include everything:
    // include: [{all:true}]
  ]
}).then(function(teams) {
  console.log(JSON.stringify(teams));
  // oneTeam.moderators: [array of User]
  // oneTeam.mentors: [array of User]
});

(side note: I think your User objects currently have a 'getMentors()' method, and a 'mentors' property, that is an array of Team. Same for the 'moderators' property. Perhaps renaming that to 'mentoredTeams' and 'moderatedTeams' would make it clearer?)

Upvotes: 6

Related Questions