I have a little problem with associations on query, I've nested assocations (4 tables, Users, A, B & C, Users hasOne A, A hasMany B and belongsTo Users, B belongsTo A and hasMany C and C belongsTo B).
When I do a findOne on Users, including my 3 other tables like that :
Models.User.findOne({
where: { id: req.user.id },
include:[{
model: Models.Candidate, // Candidate Associations (user.candidate) (Table A)
as: 'candidate',
include:[{
model: Models.Experience, // (Table B) Experiences Associations (user.candidate.experiences)
as: 'experiences',
include: [{
model: Models.Service,
as: 'service'
}
}] // Service Associations (Table C)
}]
}]
})
I correctly get the searched row but the problem is on the left outer join query of the third assocations (table C), the generated query is
LEFT OUTER JOIN `Services` AS `candidate->experiences->service` ON `candidate->experiences`.`id` = `candidate->experiences->service`.`id`
But I want to have this query :
LEFT OUTER JOIN `Services` AS `candidate->experiences->service` ON `candidate->experiences`.`service_id` = `candidate->experiences->service`.`id`
So how can I do that ?
I searched some help on google and other forum and websites but I didn't manage to find my answer since few weeks.
Thanks a lot for help that you'll provide me !
Edit :
Here is my models :
User :
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false
},
role: {
type: DataTypes.STRING
},
type: {
type: DataTypes.ENUM,
values: ['admin', 'candidate', 'es', 'demo'],
allowNull: false
}
});
User.associate = function (models) {
User.hasOne(models.Candidate, {
foreignKey: 'user_id',
as: 'candidate'
});
};
return User;
};
Candidate (A) :
'use strict';
module.exports = (sequelize, DataTypes) => {
const Candidate = sequelize.define('Candidate', {
user_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
es_id: DataTypes.INTEGER,
description: DataTypes.TEXT,
photo: DataTypes.STRING,
video: DataTypes.STRING,
status: DataTypes.STRING,
note: DataTypes.STRING,
views: DataTypes.INTEGER
}, {});
Candidate.associate = (models) => {
Candidate.belongsTo(models.User, {
foreignKey: 'id',
onDelete: 'CASCADE'
});
Candidate.hasMany(models.Experience, {
foreignKey: 'candidate_id',
as: 'experiences'
});
};
return Candidate;
};
Experience (B) :
'use strict';
module.exports = (sequelize, DataTypes) => {
const Experience = sequelize.define('Experience', {
name: {
type: DataTypes.STRING,
allowNull: false
},
candidate_id: DataTypes.INTEGER,
poste_id: DataTypes.INTEGER,
service_id: DataTypes.INTEGER,
internship: DataTypes.BOOLEAN,
start: DataTypes.DATE,
end: DataTypes.DATE,
current: DataTypes.BOOLEAN
}, {});
Experience.associate = function (models) {
Experience.belongsTo(models.Candidate, {
foreignKey: 'id',
onDelete: 'CASCADE'
});
Experience.hasOne(models.Service, {
foreignKey: 'id',
targetKey: 'service_id',
as: 'service'
});
};
return Experience;
};
Service (C) :
'use strict';
module.exports = (sequelize, DataTypes) => {
const Service = sequelize.define('Service', {
name: {
type: DataTypes.STRING,
allowNull: false
}
}, {});
Service.associate = function (models) {
Service.belongsTo(models.Experience, {
foreignKey: 'id',
onDelete: 'CASCADE'
});
};
return Service;
};
Related
I have a user, role and their relation model, when I want to insert into the relation model I get this error:
error: column "userUserId" of relation "roles_users_relationships" does not exist.
Can you help with this error?
(sorry if I wrote something wrong, this is my first question on )
This is how my model looks
Role model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles", {
role_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsToMany(models.users, {
through: "roles_users_relationship",
foreignKey: "role_id",
});
};
return table;
};
Users model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"users", {
user_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: true,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsTo(models.roles, {
through: "roles_users_relationship",
foreignKey: "user_id",
});
};
return table;
};
Roles Users relationship model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles_users_relationship", {
user_id: {
type: DataTypes.UUID,
allowNull: false,
},
role_id: {
type: DataTypes.UUID,
allowNull: false,
},
}, {
timestamps: false
}
);
return table;
};
In your through table you should add options in related table field:
references: {
model: User,
key: 'user_id'
}
Otherwise sequelize will do it automatically, like adding foreign key column in this way tableNamePrimaryKeyColumn in your case its 'userUserId'
I use postgresql/sequelize and findAndCountAll function.
Entry.findAndCountAll({
where: {TitleId: title.id},
include: [
{model: User, as: 'users', attributes: ['username']},
{model: EntryHasLike} // I need to count this. model.
],
offset: 15 * (req.body.page - 1),
limit: 15
}).then(entries => {
res.json({
title: title,
count: entries.count,
entries: entries.rows // [I want to count of likes inside this table]
})
}).catch(err => {}
I'm counting entries with findAndCountAll but I want additionally count of EntryHasLikes model which is the same with Entries.Id.
EntryHasLike model:
'use strict';
module.exports = (sequelize, DataTypes) => {
const EntryHasLike = sequelize.define('EntryHasLike', {
EntryId: {
type:DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
UserId: {
type:DataTypes.INTEGER,
allowNull: false
},
likeDate: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW
}
},{
timestamps: false
});
EntryHasLike.associate = function(models) {
EntryHasLike.belongsTo(models.User)
EntryHasLike.belongsTo(models.Entry)
};
return EntryHasLike;
};
Entry model:
'use strict';
module.exports = (sequelize, DataTypes) => {
const Entry = sequelize.define('Entry', {
UserId: {
type: DataTypes.INTEGER,
allowNull: false
},
entry: {
type: DataTypes.TEXT,
allowNull: false
},
entryRev: {
type: DataTypes.STRING,
defaultValue: 1
},
entryRefId: {
type: DataTypes.INTEGER,
defaultValue: null
},
entryCondition: {
type: DataTypes.INTEGER,
defaultValue: 1
},
activity: {
type: DataTypes.INTEGER,
defaultValue: 1
},
TitleId: {
type: DataTypes.INTEGER,
allowNull: false
}
}, {});
Entry.associate = function(models) {
Entry.belongsTo(models.Title, {foreignKey: 'TitleId', as: 'titles'})
Entry.belongsTo(models.User, {foreignKey: 'UserId', as: 'users'})
Entry.belongsToMany(models.EntryCat, {through: 'EntryHasCats', as: 'entrycats'})
Entry.belongsToMany(models.EntryTag, {through: 'EntryHasTags', as: 'entrytags'})
Entry.hasMany(models.EntryHasLike)
};
return Entry;
};
I tried many solutions but i couldn't get result. As you see related questions in below but all of about findAll function. My function is findAndCountAll
Counting associated entries with Sequelize
Sequelize 'hasMany' associated(model) count in attributes in query execution
Maybe on client you can take length of Entry.EntryHasLike
setEntry(data) {
this._entry = {
...data,
count: data.EntryHasLike.length
}
}
I am using my existing database which has no foreign keys created but I am able to join two tables using sql query but I am not able to join them in sequelize.
There are two models:
- User:
module.exports = (sequelize, DataTypes) => {
var User = sequelize.define('User', {
steamid: DataTypes.STRING,
name: DataTypes.STRING,
img: DataTypes.STRING,
tradelink: DataTypes.STRING,
ban_chat: DataTypes.INTEGER,
block_sms: DataTypes.INTEGER,
balance: DataTypes.INTEGER,
ref: DataTypes.STRING,
refcode: DataTypes.STRING,
ip_address: DataTypes.STRING
}, {
timestamps: false
});
User.associate = function(models) {
// associations can be defined here
User.hasMany(models.Order,{
foreignKey: 'steamid',
as: 'orders'
});
};
return User;
};
Order:
const customDataTypes = require('../../core').SequelizeTimestamp;
module.exports = (sequelize, DataTypes) => {
var Order = sequelize.define('Order', {
steamid: DataTypes.STRING,
item_name: DataTypes.STRING,
price: DataTypes.FLOAT,
type: DataTypes.STRING,
website: DataTypes.STRING,
amount: DataTypes.INTEGER,
status: DataTypes.INTEGER,
img: DataTypes.STRING,
send_attempts: DataTypes.INTEGER,
message: DataTypes.STRING,
date: customDataTypes.TIMESTAMP,
}, {
timestamps: false
});
Order.associate = function(models) {
// associations can be defined here
Order.belongsTo(models.User, {
foreignKey: 'steamid',
as: 'user'
})
};
return Order;
};
In my API i want to get user and his orders.
So in the controller i am doing:
user.findOne({
where: { steamid: req.params.steamId },
include: [{
model: order,
as: 'orders',
limit: 50
}],
})
So I expect to have user order array in the response but for some reason I get empty orders array.
Sequelize is doing these two queries:
SELECT `User`.`id`, `User`.`steamid`, `User`.`name`, `User`.`img`, `User`.`tradelink`, `User`.`ban_chat`, `User`.`block_sms`, `User`.`balance`, `User`.`ref`, `User`.`refcode`, `User`.`ip_address` FROM `Users` AS `User` WHERE `User`.`steamid` = '1234' LIMIT 1;
This is successfully finding the user but the second query is incorrect:
SELECT `id`, `steamid`, `item_name`, `price`, `type`, `website`, `amount`, `status`, `img`, `send_attempts`, `message`, `date` FROM `Orders` AS `Order` WHERE `Order`.`steamid` IN (1) LIMIT 50;
This part is incorrect "WHERE Order.steamid IN (1)"
It is looking for orders which steamid is = 1 which is user id (primary key) but it should be user steamid which is "1234"
What is wrong with my associations?
If steamid is not a primary you should`t be using "targetKey" and "sourceKey"?
https://sequelize.org/master/manual/associations.html
Order.belongsTo(models.User, {
foreignKey: 'steamid',
targetKey: 'steamid',
as: 'user'
})
Order.belongsTo(models.User, {
foreignKey: 'steamid',
sourceKey: 'steamid',
as: 'user'
})
I'm new to Sequelize and trying to test if an n:m association I set up between two models, User and Podcast, is working. When I try to run this query, I get some kind of DB error that isn't specific about what's wrong:
User.findOne({
where: { id: id },
include: [{ model: Podcast }]
});
Does anyone know what I'm messing up? I suspect there's something wrong in how I've set up the association, like I'm referencing the names of tables slightly incorrectly, but the migration to create the association worked.
Here's my User.js model file:
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
photo: {
type: DataTypes.STRING
}
});
User.associate = function(models) {
// associations can be defined here
User.belongsToMany(models.Podcast, {
through: 'user_podcast'
});
};
return User;
};
And here's my Podcast.js file:
'use strict';
module.exports = (sequelize, DataTypes) => {
const Podcast = sequelize.define('Podcast', {
id: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false
},
title: {
type: DataTypes.STRING,
allowNull: false
},
thumbnail: {
type: DataTypes.STRING
},
website: {
type: DataTypes.STRING
}
});
Podcast.associate = function(models) {
// associations can be defined here
Podcast.belongsToMany(models.User, {
through: 'user_podcast'
});
};
return Podcast;
};
And here's the migration I ran to join the two tables:
'use strict';
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('user_podcast', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER,
references: {
model: 'Users',
key: 'id'
}
},
podcastId: {
type: Sequelize.STRING,
references: {
model: 'Podcasts',
key: 'id'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable('user_podcast');
}
};
And here's the project on Github for further reference:
https://github.com/olliebeannn/chatterpod
You don't need to create a migration for the M:N table. Now you have something wrong on your user_podcast model. If you are setting a M:N relation between to tables your primary key will be the combination between the foreign key from these two models. If you still want a single id primary key for your table, then you won't use belongsToMany instead use hasMany on user and podcast models pointing to a new model user_podcast.
As far as I see on your first query, it seems that you really need a M:N relation so you can define the model as you do with user and podcast like this:
module.exports = (sequelize, DataTypes) => {
const UserPodcast = sequelize.define('user_podcast', {
userId: {
// field: 'user_id', #Use 'field' attribute is you have to match a different format name on the db
type: DataTypes.INTEGER
},
podcastId: {
// field: 'podcast_id',
type: DataTypes.INTEGER
},
});
UserPodcast.associate = function(models) {
models.User.belongsToMany(models.Podcast, {
as: 'podcasts', //this is very important
through: { model: UserPodcast },
// foreignKey: 'user_id'
});
models.Podcast.belongsToMany(models.User, {
as: 'users',
through: { model: UserPodcast },
// foreignKey: 'podcast_id'
});
};
return UserPodcast;
};
I do prefer to have the belongsToMany associations on the save function where I define the join model, and you have to notice that I used as: attribute on the association. This is very important because this will help sequelize to know which association are you referring on the query.
User.findOne({
where: { id: id },
include: [{
model: Podcast,
as: 'podcasts' //here I use the previous alias
}]
});
How make autoclear relation table when one of entity deleted ? Now when I delete task or type in relation table tasks_types_realations still exist record with id of deleted entity, for example I have task with id: 1, and type with id: 1, in relation table it will |taskId:1|typeId:1|, and after delete task or type record still exist.
Task model:
module.exports = (sequelize, DataTypes) => {
const Task = sequelize.define('task', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
status: {
type: DataTypes.ENUM,
values: ['done', 'pending', 'cancel'],
defaultValue: 'pending',
allowNull: false
},
date: {
type: DataTypes.DATE,
allowNull: false
},
})
Task.associate = models => {
Task.TaskType = Task.belongsToMany(models.TaskType, {
as: 'types',
through: models.TasksTypes
})
}
return Task
}
Type model:
module.exports = (sequelize, DataTypes) => {
const TaskType = sequelize.define(
'taskType',
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
unique: true
}
},
{
tableName: 'tasks_types'
}
)
TaskType.associate = models => {
TaskType.Task = TaskType.belongsToMany(models.Task, {
as: 'tasks',
foreignKey: 'typeId',
through: models.TasksTypes
})
}
return TaskType
}
In task model add:
Task.TasksTypes = Task.hasMany(models.TasksTypes, {
as: 'typesRelations',
foreignKey: 'taskId',
hooks: true,
onDelete: 'cascade'
})
In type model add:
TaskType.TasksTypes = TaskType.hasMany(models.TasksTypes, {
as: 'tasksRelations',
foreignKey: 'typeId',
hooks: true,
onDelete: 'cascade'
})