many-to-many-to-many query
See original GitHub issueIssue Description
I’m trying to get an output like this:
[{
"Id": 1,
"Name": "Game 1",
"Teams": [{
"Id": 1,
"Name": "Team 1",
"Users": [{
"Id": 1,
"UserName": "User 1"
}]
}]
}, {
"Id": 2,
"Name": "Game 2",
"Teams": [{
"Id": 1,
"Name": "Team 1",
"Users": [{
"Id": 2,
"UserName": "User 2"
}]
}]
}]
Note that Team 1 has 2 different users, but that’s only because they’re set up that way per game… so a user isn’t tied directly to a team, but rather through a team game constraint. Basically, my Game HasMany Teams, and my Game/Team HasMany Users… a many-to-many-to-many relationship. I was trying to follow this thread, but it seems like what they’re doing there doesn’t actually work, as I tried doing this:
// models/Game.js
module.exports = (sequelize, types) => {
const GameModel = sequelize.define('Game', {
Id: {
type: types.INTEGER,
primaryKey: true,
autoIncrement: true
},
Name: {
type: types.STRING,
allowNull: false
}
});
GameModel.associate = (models) => {
GameModel.belongsToMany(models.Team, {
as: 'Teams',
foreignKey: 'GameId',
through: models.GameTeam
});
};
return GameModel;
};
// models/Team.js
module.exports = (sequelize, types) => {
const TeamModel = sequelize.define('Team', {
Id: {
type: types.INTEGER,
primaryKey: true,
autoIncrement: true
},
Name: {
type: types.STRING,
allowNull: false
}
});
TeamModel.associate = (models) => {
TeamModel.belongsToMany(models.Game, {
as: 'Games',
foreignKey: 'TeamId',
through: models.GameTeam
});
};
return TeamModel;
};
// models/User.js
module.exports = (sequelize, types) => {
const UserModel = sequelize.define('User', {
Id: {
type: types.INTEGER,
primaryKey: true,
autoIncrement: true
},
UserName: {
type: types.STRING,
allowNull: false
}
});
return UserModel;
};
// models/GameTeam.js
module.exports = (sequelize, types) => {
const GameTeamModel = sequelize.define('GameTeam', {
Id: {
type: types.INTEGER,
primaryKey: true,
autoIncrement: true
}
});
GameTeamModel.associate = (models) => {
GameTeamModel.belongsToMany(models.User, {
as: 'Users',
through: 'GameTeamUser'
});
};
return GameTeamModel;
};
// models/GameTeamUser.js
module.exports = (sequelize, types) => {
const GameTeamUserModel = sequelize.define('GameTeamUser', {
Id: {
type: types.INTEGER,
primaryKey: true,
autoIncrement: true
}
});
return GameTeamUserModel;
};
The above models create the tables just fine, with what appears to be the appropriate columns. I then do some inserts and try to use a findAll on the Game model like this:
GameModel.findAll({
include: [{
association: GameModel.associations.Teams,
include: [{
association: GameTeamModel.associations.Users,
through: {
attributes: []
}
}],
through: {
attributes: []
}
}]
});
The query starts to go wrong at the 2nd include with the association of the Users. Because I’m trying to nest the users inside of the teams, I figured the join would attempt to use the unique ID on the through table (GameTeams.Id), but instead, the query ends up using this:
LEFT OUTER JOIN `GameTeamUser` AS `Teams->Users->GameTeamUser` ON `Teams`.`Id` = `Teams->Users->GameTeamUser`.`GameTeamId`
I figured the ON would be GameTeams.Id = Teams->Users->GameTeamuser.GameTeamId
, but I don’t know why it’s not, and how to adjust it… I’ve tried using a custom on
in my include (per the docs), but it seems to be ignored completely. Anyone have any advice? Or possibly a better way of structuring this, so it works the way I want it to?
StackOverflow / Slack attempts
Additional context
package.json deps (using SQLite as the backing DB):
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "~4.16.1",
"ip": "^1.1.5",
"morgan": "~1.9.1",
"sequelize": "^5.21.3",
"sequelize-cli": "^5.5.1",
"sqlite3": "^4.1.1"
}
Is this issue dialect-specific?
[ ] No. This issue is relevant to Sequelize as a whole. [ ] Yes. This issue only applies to the following dialect(s): XXX, YYY, ZZZ [✔] I don’t know.
Would you be willing to resolve this issue by submitting a Pull Request?
[ ] Yes, I have the time and I know how to start. [✔] Yes, I have the time but I don’t know how to start, I would need guidance. [ ] No, I don’t have the time, although I believe I could do it if I had the time… [ ] No, I don’t have the time and I wouldn’t even know how to start.
Issue Analytics
- State:
- Created 4 years ago
- Comments:19 (7 by maintainers)
@papb although your new many-to-many-to-many example in the docs is a solution, it’s not ideal because it requires two join tables (
GameTeam
andPlayerGameTeam
), whereas using raw SQL, it’s possible to have a single join table with all three foreign keys. Imagine if someone has a pre-existing database with a three-way join table and tries to start using Sequelize on it…they would have to keep using raw SQL. I think an API like this would be a welcome addition:I’m not entirely convinced it has changed… it started out with me asking how to get that output, and I still haven’t learned how to do that naturally through the ORM without doing manual manipulation… unless that is the only way of doing it. It really sounds like this is not possible in the current version though, so I guess I’ll just have to chalk it up to that’s what I get for using this ORM.