I'm attempting to eager load a belongs-to-many
association where I am loading three nested associations. Here are the models, which result in three database tables programs
, programDates
and peopleProgramDates
program.js
:
module.exports = function(sequelize, DataTypes) {
const Program = sequelize.define('program', {
name: DataTypes.STRING
});
Program.associate = ({programDate}) => {
Program.hasMany(programDate);
};
return Program;
};
program_date.js
:
module.exports = function(sequelize, DataTypes) {
const ProgramDate = sequelize.define('programDate', {
date: DataTypes.DATEONLY,
volunteerLimit: DataTypes.INTEGER
}, {
indexes: [
{
unique: true,
fields: ['programId', 'date']
}
]
});
ProgramDate.associate = ({program, person}) => {
ProgramDate.belongsTo(program);
ProgramDate.belongsToMany(person, {through: 'peopleProgramDates'});
};
return ProgramDate;
};
In my controller, I want to return an object with all of the programs, programDates and peopleProgramDates:
const {bus, family, person, volunteerType, program, programDate} = require('../models');
exports.get = (request, response) => {
return Promise.all([
bus.findAll({ include: [{model: family, include: [person]}] })
.then(buses => buses.map(addBusCount)),
volunteerType.findAll({include: [person]})
.then(volunteerTypes => volunteerTypes.map(addVolunteerCount)),
// this query hangs the application
program.findAll( { include: [{ model: programDate, include: [{association: 'peopleProgramDates'}] }]} )
.then(programs => programs.map(processPrograms))
])
.then(([buses, volunteerTypes, programs]) =>
response.render('pages/register', {
buses,
volunteerTypes,
programs
})
);
};
At the moment, processPrograms()
is a function that simply returns the same array of objects, and so should not be relevant here. addBusCount
and addVolunteerCount
should similarly not be relevant.
I think the issue may be that peopleProgram dates is not a real sequelize model, but the result of the the belongsToMany through:
association on ProgramDate
.
This post seems to suggest I can use the association:
property in order to load the data from the through
association, however the query hangs the application.
If I remove the join table from the query, then the data loads fine:
program.findAll( { include: [programDate] } )
Bonus points: Ultimately what I really need is simply a count of peopleProgramDates
returned with the programDate
objects. Perhaps I can simply define such on the programDates
model, however perhaps we can address that in a separate question. Nevertheless, if there is a compelling reason to use this approach, such as performance, then maybe we should go that way after all.
The solution was to add an alias to the belongsToMany
through association:
// program_date.js
ProgramDate.belongsToMany(person, {through: 'peopleProgramDates', as: 'peopleProgDates'});
And then reference the alias in the include
property:
program.findAll( { include: [{ model: programDate, include: [{association: 'peopleProgDates'}] }]} )
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.