-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
include on hasMany association only returning one of many results when no primary key #5193
Comments
When we process associations we attempt to dedupe each row by either matching primary keys or row uniqueness. Any chance the task rows are completely equal? |
Looks like this is occurring when a field in the table is named 'id'. Here's a test case:
If you remove the |
|
I'm having the same issue. Codevar User = sequelize.define('User', { name: Sequelize.STRING })
var Task = sequelize.define('Task', { name: Sequelize.STRING })
Task.removeAttribute('id') // This line is causing all the problems
Task.belongsTo(User, { foreignKey: 'User_ID', as: 'User' })
User.hasMany(Task, { foreignKey: 'User_ID' })
User.sync({ force: true })
.then(function () { return Task.sync({ force: true }) })
.then(function () {
return User.create({
name: 'Foo',
Tasks: [
{ name: 'Baz' },
{ name: 'Bar' },
{ name: 'Boris' },
{ name: 'Barata' }
]
}, { include: [ { all: true } ] })
})
.then(function () {
User
.all({ include: [ { all: true } ] })
.then(function (users) {
users.map(function (user) {
console.log(user.toJSON())
})
})
}) ResultWithout
Commenting the
SQLThe SELECT queries generated (with and without SELECT "User"."id", "User"."name", "Tasks"."name" AS "Tasks.name", "Tasks"."User_ID" AS "Tasks.User_ID" FROM "Users" AS "User" LEFT OUTER JOIN "Tasks" AS "Tasks" ON "User"."id" = "Tasks"."User_ID";
SELECT "User"."id", "User"."name", "Tasks"."id" AS "Tasks.id", "Tasks"."name" AS "Tasks.name", "Tasks"."User_ID" AS "Tasks.User_ID" FROM "Users" AS "User" LEFT OUTER JOIN "Tasks" AS "Tasks" ON "User"."id" = "Tasks"."User_ID"; Identical with the exception of the extra column FinalI also found that the method |
Is there a way to prevent this behavior? Lets say we have branches and employees. An employee can be associated to multiple branches and have multiple supervisors (other employees) in each branch. Employee model definition:
Branch model definition:
Join table:
If I want every supervisor for a particular employee, I'd do something like:
However, if an employee has the same supervisor in multiple branches I'd only get the supervisor once, which could be fine in some cases. But the |
👍 Having the exact same problem on a model with the id removed. |
is this issues has been fixed ? |
...So does this mean the "hasMany" functionality doesn't actually do what it's supposed to? |
I'm seeing similar behavior as @thevtm. As soon as I include the primary key back into the attributes I get the full list. But when that Id is not selected then I only get the first of many, even though all of the records are unique. |
I just had the same problem. I ended up having to create an useless id column. |
@renatoargh Can you comment more on what you're doing to get the includes to work? I can't seem to figure it out. Thanks |
Do tables with composite primary keys is affected also? I face a severe trouble here also that results in first row only |
@rttomlinson If you are still facing this issue the workaround is to add primary key field to the table and include that field in your query or make composite unique key and include them in your select query. for ex:
This is how I got things work. |
This comment has been minimized.
This comment has been minimized.
I am having this same issue, is there any additional info regarding how to fix it? |
Any update on this? |
Seems like this one to many mapping has been bugging off a lot of people :( |
My problem is similar but slightly different. I'm fetching the raw data with The product has a many-to-many association with
db.models.product.findAll({
raw: true,
include: [{ all: true }]
} ); |
@holmberd I think if you remove the |
@uncedric it sure will, but I don't need the objects, only the raw data.
|
I know! I have the same problem :( |
I also fix this problem by removing { raw: true} from my Model.findAll function |
Looking into the libraries it seems to stem from the conditional statement if (this.options.raw) {
result = results.map(result => {
let o = {};
for (const key in result) {
if (result.hasOwnProperty(key)) {
o[key] = result[key];
}
}
if (this.options.nest) {
o = Dot.transform(o);
}
return o;
});
// Queries with include
} else if (this.options.hasJoin === true) {
results = AbstractQuery._groupJoinData(results, {
model: this.model,
includeMap: this.options.includeMap,
includeNames: this.options.includeNames
},
....
// return the first real model instance if options.plain is set (e.g. Model.find)
if (this.options.plain) {
result = result.length === 0 ? null : result[0];
}
return result; Assuming Example of results input(see below) for the var results = [
{
some: 'data',
id: 1,
association: { foo: 'bar', id: 1 }
}, {
some: 'data',
id: 1,
association: { foo: 'bar', id: 2 }
}, {
some: 'data',
id: 1,
association: { foo: 'bar', id: 3 }
}
]; I've seen people complain about association count giving false result for the |
Hard to believe... I just added
This is the SQL generated: SELECT "Cart"."id",
"items"."id" AS "items.id",
"items"."name" AS "items.name",
"items"."price" AS "items.price",
"items->CartItem"."id" AS "items.CartItem.id",
"items->CartItem"."qty" AS "items.CartItem.qty",
"items->CartItem"."createdAt" AS "items.CartItem.createdAt",
"items->CartItem"."updatedAt" AS "items.CartItem.updatedAt",
"items->CartItem"."CartId" AS "items.CartItem.CartId",
"items->CartItem"."ProductId" AS "items.CartItem.ProductId"
FROM "Carts" AS "Cart"
LEFT OUTER JOIN ("CartItems" AS "items->CartItem"
INNER JOIN "Products" AS "items" ON "items"."id" = "items->CartItem"."ProductId") ON "Cart"."id" = "items->CartItem"."CartId"
WHERE "Cart"."id" = '1'; And this is the result if I run the query manually: Now, if I set only const options = {
include: [ { model: Product, as: 'items' } ],
where: { id: '1' },
};
Cart.findOne(options)
.then(data => console.log(data.items.length)); // this will be 1 (but `items` should have 2 rows) IMHO this is a critical issue because otherwise we can't be completely confident on this feature, or we're missing something else?
That would be the problem in my case because:
Both rows on the
There's a way to disable that deduplication/uniqueness check? Thank you! |
worked for me too... |
I had the same error, added composite pk to multiple columns of model without |
Hey, i have same issue, have any fix?
|
The solution that worked for me:
Full disclosure: I'm not the most experienced Dev, nor do i work on large complex applications but hey this may help someone. Cheers |
Hey bro i tried, but after added sourceKey gived me 'UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'field' of undefined' this error.
|
i had this error and it led to one of my models not having that field in it. do you have 'id' in your User Model? the sourceKey references User the User Model like i say i haven't got lots of experience but maybe this helps? |
Users and Payments model has id also Payments model has user_id |
Hey mate so the way I see it is you need to try User hasMany Payments : change sourceKey to ‘id’. |
Hey mate thank you for help; After edit;
|
I solved this problem by first fetching as a raw sequelize object, then calling .toJSON() on it. Example: The relationship between Post and Comment is shown below: |
So has anyone really found a fix to this problem? This thread evolved into two different issues. The second issue having to do with I am having the original problem from the opening comment. Our MSSQL db doesn't want Sequelize to Insert_Identity so the Primary Key is disabled to allow creation coupled with Model.removeAttribute('id'). On Read queries, hasMany loads only one record. @lekhnath commented on setting up a composite unique key, but I haven't had success with that either. Any thoughts left out there? |
Additionally I would like to add an example: Foo.hasMany(bar) Foo does not need the PK declared for it to work properly. Once you declare the PK on Bar, then it will fetch all of the associations. Funny thing is that the SQL generated by both setups is exactly the same and they both retrieve all the association when inputted directly into SQL Server console. It seems that Sequelize configurations is blocking the rendering of all the associations. |
Not sure if 100% related to this - but we had an issue with a many to many relationship where the solution of using a primary key was found by a coworker in this documentation link https://sequelize.org/master/manual/advanced-many-to-many.html We defined the ID in the Model as said and it all worked - so maybe it is not exactly an issue, more of a misunderstanding when using sequelize, or how sequelize does things. Just adding it because nobody pointed in the direction of that link and might be helpful.
|
This is great stuff right here. Our problem specifically is that we cannot declare primaryKeys at all with our ORM because SQL Server does not want the ORM to Insert_Identity. So we are creating associations with out declaring the primary key. Ex: `@Table @column({primaryKey: false}) @hasmany(() => Bar, { @table @column({primaryKey: false}) @ForiegnKey( () => Foo, ) @BelongsTo(() => Foo, { ` |
Still no fix?! |
I still having this issue, tested on latest v6 and v7 ( SQLITE ) . And problem seems to be bigger, because it happens even you add an id. Every "find" function using There are a lot of issues related, and since this seems to be the main thread of the issue, it could be renamed to match better the problem. ( 'raw' is the main keyword, 'primary key' seems not relevant since it happens any ways using it ) Generated SQL statments are the same using raw or not, so is some parsing issue. Have some one some aproach ( with raw: true ) to get the correct data ?? Or some clue to find a fix ?? Or where to look on Sequelize for a fix ?? |
Sorry for the notification, Ignore my misclick 🤦♀️ |
I have exactly the same problem, is there already a solution so that it can be used with |
This comment was marked as off-topic.
This comment was marked as off-topic.
Ran into this issue today despite having a Primary Key. The problem for me was my PK was 2 columns. As a workaround i added id: {
type: DataTypes.BIGINT.UNSIGNED,
autoIncrement: true,
primaryKey: true,
}, to my associated model and removed the original 2 columns from PK, now all results are returned correctly. Would be great if this issue could be resolved (and also support PKs that consist of more than a single column) |
Use :- |
I had the same problem in v 6.37.1 and that fixed it |
I looked around for this issue and couldn't find it mentioned exactly as I'm seeing it, so apologies in advance if this is a duplicate. The issue is that when I use include like so:
Project.findAll({ include: [{ model: Task }], where: { ... } })
the query is generated correctly and the correct projects are returned, but each contains an array of Tasks that is always of length one (when the Tasks have no primary key), even though many tasks match. I can confirm this using the raw query and verifying the results. If I add a primary key to Task, it then works correctly.
Here are the related definitions, in case there are some clues there.
The text was updated successfully, but these errors were encountered: