Many-to-many "through" table with multiple rows of identical foreign key pairs only returns one result
See original GitHub issueI’m using the mysql
dialect with sequelize@^2.0.5
.
My database is set up such that I have users
and items
. Users can mark items as “owned”, and for this I have an ownership
table. My scenario allows for users to mark the same item as owned multiple times while including some additional data — for this example, a note — about one of the ownerships.
Here’s an example of the ownership
table:
id | userId | itemId | notes |
---|---|---|---|
1 | 50 | 941 | This is my green one. |
2 | 50 | 941 | This is my blue one. |
My models are defined as follows:
var User = sequelize.define('user', {
username: DataTypes.STRING
});
var Item = sequelize.define('item', {
title: DataTypes.STRING
});
var Ownership = sequelize.define('ownership', {
id: {
type: DataTypes.INTEGER,
primaryKey: true
},
notes: DataTypes.TEXT
});
Item.belongsToMany(User, { through: Ownership });
User.belongsToMany(Item, { through: Ownership });
I am explicitly defining the id
primary key on the Ownership
model because of this paragraph in the Sequelize documentation:
Relations/Associations -> Belongs-To-Many Associations
By default the code above will add ProjectId and UserId to the UserProjects table, and remove any previsouly defined primary key attribute - the table will be uniquely identified by the combination of the keys of the two tables, and there is no reason to have other PK columns. To enforce a primary key on the UserProjects model you can add it manually.
When I fetch a user, I would like both of of the Items
for the User
to be available in the model, however only one is. The SQL that is output in the console is correct and does in fact return two results, but I think something internally in Sequelize is removing the other — perhaps looking at the foreign keys to determine the uniqueness of the Item
. Based on the paragraph in the documentation, I assumed that adding the id
attribute to the Ownership
model would fix this and treat each one uniquely.
User.find({
where: { id: 50 },
include: [{ all: true, nested: true }]
}).then(function(user) {
console.log(JSON.stringify(user));
});
Expected:
{
"id": 50,
"username": "john",
"items": [{
"id": 1,
"title": "foobar",
"ownership": {
"id": 1,
"userId": 50,
"itemId": 941,
"notes": "This is my green one."
}
}, {
"id": 1,
"title": "foobar",
"ownership": {
"id": 2,
"userId": 50,
"itemId": 941,
"notes": "This is my blue one."
}
}]
}
Actual:
{
"id": 50,
"username": "john",
"items": [{
"id": 1,
"title": "foobar",
"ownership": {
"id": 2,
"userId": 50,
"itemId": 941,
"notes": "This is my blue one."
}
}]
}
I hope this all makes sense, and I very much appreciate any help or direction if I am doing something wrong.
Issue Analytics
- State:
- Created 8 years ago
- Reactions:20
- Comments:63 (9 by maintainers)
Dear bot this issue is still there. 😃
Yes this is issue is very relevant. I honestly think it is one of the biggest drawbacks currently.