get associations with belongsToMany in sequelize.js - node.js

I have a many-to-many relation between User and Device model, through a UserDevice join table:
device.belongsToMany(user, {
through: {
model: userDevice
},
foreignKey: "deviceId",
as: "customers"
});
user.belongsToMany(device, {
through: {
model: userDevice
},
foreignKey: "customerId",
as: "devices"
});
setCustomers: Sequelize.BelongsToManySetAssociationsMixin<UserInstance, string, UserDeviceAttribute>;
getCustomers: Sequelize.BelongsToManyGetAssociationsMixin<UserInstance>;
I can find devices and populate customers correctly with:
this.db.models.Device.findAll({
include: [{
model: User,
as: "customers"
}]
I can't figure out how I can populate customers in other scenarios, i.e. when I'm setting customers manually. Right now I'm trying something like:
return device.setCustomers(customers)
.then(() => {
return device.getCustomers();
})
.then((users) => {
device.setAttributes("customers", users);
return device;
});
but it's not working, setAttributes doesn't set customers field.

The answer is in the question. I found the bug today when encountered same issue.
https://github.com/sequelize/sequelize/blob/master/lib/model.js#L3483
setAttributes seems to be a reserved method for sequelize.

Related

Sequelize unable to model this relationship. X is not associated to Y

I have an Orders and Transactions table.
The id in Orders is to be used in the sellOrderId and buyOrderId columns
To model this in my Orders table I have
static associate({ Transactions }) {
Orders.hasMany(Transactions, { foreignKey: 'buyOrderId', sourceKey: 'id', as: 'buyTransactions' });
Orders.hasMany(Transactions, { foreignKey: 'sellOrderId', sourceKey: 'id', as: 'sellTransactions' });
}
In my Transactions model I have
static associate({ Orders }) {
Transactions.belongsTo(Orders, { foreignKey: 'id', targetKey: 'sellOrderId' });
Transactions.belongsTo(Orders, { foreignKey: 'id', targetKey: 'buyOrderId' });
}
I am attempting to get all Orders along with their associated transactions
I have tried many different queries but they all error out with the same error
EagerLoadingError [SequelizeEagerLoadingError]: Transaction is not associated to Orders!
Currently I have
const orders = await Order.findAll({
include: [
{
model: Transaction,
as: 'buyTransactions'
},
{
model: Transaction,
as: 'sellTransactions'
}
]
});
Regardless of if I have one or both same error, I can see in the database that the relationship exists, Im not sure why sequelize is not honoring this.

Multiple Sequelize Associations

I have a few associations between models like so:
Patient.hasMany(Transaction, {
as: 'transactions',
foreignKey: 'patient_id',
sourceKey: 'id'
});
Transaction.belongsTo(Patient, {
as: 'patient',
foreignKey: 'patient_id',
targetKey: 'id'
});
Transaction.hasMany(Transaction, {
as: 'transactions',
foreignKey: 'item_to_pay',
sourceKey: 'id'
});
I'm writing a query to get a list of transactions that belong to a patient and include the models associated with them:
Transaction.findAll({
where: {
patient_id: 1
},
include: [{
model: Patient,
as: 'patient',
attributes: ['first_name']
}, {
model: Transaction,
as: 'transactions',
include: [{
model: Patient,
as: 'patient',
attributes: ['first_name']
}]
}],
});
However when the result returns, it does not include the second nested patient model as I expect it to.
I've also tried writing a different query to see if I can get the desired result:
Transaction.findAll({
where: {
patient_id: 1
},
include: [{
model: Transaction,
as: 'transactions',
include: [{
model: Patient,
as: 'patient',
attributes: ['first_name']
}]
}],
});
But this query errors out and returns 'Unknown column 'patient.id' in field list'.
Does anyone see something wrong with my query or associations? Is there something I'm not understanding about the associations here?
I ended up changing my original query since I couldn't figure it out at the time. I stumbled into the same issue recently and realized the issue came from how I named my associations. I named the transaction.hasMany association as transactions which ended up confusing MySQL with the query that was generated because one of the tables is named transactions.
TLDR, don't name your associations the same name as any of your table names.

many to many association in node js

here is link of my code . I am getting error in index.js in api-routes-index.js. getting error undefined map function
I guess here you have an error:
subcategories: products.subcategories.map(Subcategory => {
products is array, you can't get subcategories from array. Change it to this code:
subcategories: Product.subcategories.map(Subcategory => {
Many to many associations in sequilize.js
This will be helpful for you to solve the issue:
One product has many order
One order has many product
As a result of many to many we have junction table "orderproduct" which contains product_id and order_id.
// In product model
product.belongsToMany(order, {
through: 'orderproduct',
foreignKey: 'product_id'
});
// In order model
order.belongsToMany(product, {
through: 'orderproduct',
foreignKey: 'order_id'
});
// In oderproduct model
orderproduct.belongsTo(product, {
foreignKey: { name: 'product_id', allowNull: false }
});
orderproduct.belongsTo (order, {
foreignKey: { name: 'order_id', allowNull: false }
});
}

Sequelize: Joining Many to Many tag table with another table in postgresql

I am trying to setup many to many relationship in Sequelize for my Postgres tables using a tag (lookup) table. I was successful in setting up the relationship.
Now my lookup table, has an additional field which is a foreign key to another table. I want the data for that table to be included in my result set. This is where I am having hard time figuring out the syntax.
My models:
Models.user = sequelize.define('user', { //attributes});
Models.school = sequelize.define('school', { //attributes });
Models.role = sequelize.define('role', { //attributes });
Models.userSchools = sequelize.define('user_school', {
user_school_id: { type: Sequelize.INTEGER, primaryKey: true }
});
Models.user.belongsToMany(Models.school, { through: Models.userSchools, foreignKey: 'user_id', otherKey: 'school_id' });
Models.school.belongsToMany(Models.user, { through: Models.userSchools, foreignKey: 'school_id', otherKey: 'user_id' });
Models.userSchools.belongsTo(Models.role, { foreignKey: 'role_id' });
Working query: This query gives me all the users and their schools.
Models.user.findAll({
where: {
//condition
},
include: [Models.school]
})
Now I want to include the role for each schools. None of the below queries are working.
Models.user.findAll({
where: {
//conditions
},
include: [Models.schools, Models.role]
})
Above query is throwing an error saying role is not associated to user, which is expected.
Models.user.findAll({
where: {
//conditions
},
include: [Models.schools, {model: Models.userSchools, include: Models.role}]
})
This query is also throwing an error:
"userSchools is not associated to user".
Can any one help with syntax to how I can get the role information from the userSchools model?
Edit:
I have add a "through" condition which gets me the role_id but not the related role data.
Models.user.findAll({
where: {
//conditions
},
include: [{
model: Models.school,
as: 'schools',
through: {
attributes: ['role_id']
}
}]
})

Get Count of Sequelize BelongsToMany Association

I have two models, project and user that are associated with each other in a few ways.
First, a project is owned by a user with the following association:
Project.belongsTo(models.User, { as: 'Owner', foreignKey: 'userId' });
Secondly, a project and user are associated by way of a user liking a project.
Project.belongsToMany(models.User, { as: 'UserLikes', through: models.ProjectLikes, foreignKey: 'projectId' });
User.belongsToMany(models.Project, { as: 'LikedProjects', through: models.ProjectLikes, foreignKey: 'userId' });
Thirdly, a project and user can also be associated by way of a user being part of a project via a Role.
Project.belongsToMany(models.User, { as: 'Users', through: models.ProjectRoles, foreignKey: 'projectId' });
User.belongsToMany(models.Project, { as: 'Roles', through: models.ProjectRoles, foreignKey: 'userId' });
What I am trying to achieve is to find all projects and along with them return the associated "like" count. However I am really struggling to figure out how to do this.
I have read that I should be able to do something like:
models.Project.findAll({
limit: 5,
attributes: ['Project.*', [models.sequelize.fn('COUNT', models.sequelize.col('UserLikes.id')), 'totalLikes']],
include: [ { model: models.User, as: 'UserLikes' }],
group: [ models.Project.rawAttributes.id, models.sequelize.col('UserLikes.id') ]
})
.then(function (projects) {
return res.json(projects);
});
But I get a missing FROM-clause entry for table "UserLikes error.
I've tried changing the associations on both sides to hasMany using a specific joining-table model and then doing:
models.Project.findAll({
limit: 5,
attributes: ['Project.*', 'ProjectLikes.id', [models.sequelize.fn('COUNT', models.sequelize.col('ProjectLikes.id')), 'totalLikes']],
include: [ { model: models.ProjectLikes }],
group: [ models.Project.rawAttributes.id ]
})
.then(function (projects) {
return res.json(projects);
});
But I get the same error, or errors about Ids being ambiguous or errors about Project.id needing to be in the GROUP BY clause (even though it is?!).
I am tearing my hair out trying to figure out something that should be really straight forward... I am almost considering switching back to MongoDB!
Please help... Thanks!
I have the same problem for belongsToMany, but I managed to solve it for hasMany. You have to put attributes: [] for models.ProjectLikes (inside the include) and for fixing the limit bug you have to put subQuery: false in the findAll options.

Resources