How can I specify a foreign key, when i make a query that include another model, because i have many foreign keys for that model.
DBTweet.findAll({ where: { userID: followingUserID }, include: [
{ model: DBUser,
include: [
{ model: DBFollower // Here i want to specify the foreign key },
] },
]})
UPDATE:
When i have two associations with as
users is associated to followers multiple times. To identify the correct association, you must use the 'as' keyword to specify the alias of the association you want to include
DBFollower.findAll({ where: { followerUserID: req.params.userID }, include: [
{ model: DBUser, attributes: { exclude: ['email', 'password', 'loginType', 'telephoneNumber'] }}
]})
Those are my associations :
DBUser.hasMany(DBTweet, { foreignKey: 'userID' }, { onDelete: 'cascade' })
DBTweet.belongsTo(DBUser, {foreignKey: 'userID'}, { onDelete: 'cascade' })
DBUser.hasMany(DBFollower, { as: 'followingUserIDAlias', foreignKey: 'followingUserID' }, { onDelete: 'cascade' })
DBFollower.belongsTo(DBUser, { as: 'followingUserIDAlias', foreignKey: 'followingUserID' }, { onDelete: 'cascade' })
DBUser.hasMany(DBFollower, { as: 'followerUserIDAlias', foreignKey: 'followerUserID' }, { onDelete: 'cascade' })
DBFollower.belongsTo(DBUser, { as: 'followerUserIDAlias', foreignKey: 'followerUserID' }, { onDelete: 'cascade' })
DBTweet.findAll({
where: { userID: followingUserID },
include: [{
model: DBUser,
as: 'Users', //here goes the alias as well
include: [{
model: DBFollower,
as: 'Followers' //here is goes the alias of the association
}],
}]
});
module.exports = (sequelize, DataTypes) => {
const DBUser = sequelize.define('DBUser', {
// your attributes
});
DBUser.associate = (models) => {
DBUser.hasMany(models.DBFollower, { as: 'Followers', foreignKey: 'your_key' });
// DBUser.belongsTo(models.DBFollower, { as: 'Followers', foreignKey: 'branch_id' });
};
return DBUser;
};
UPDATE:
Now with your associations:
DBUser.hasMany(DBTweet, { as: 'Users', foreignKey: 'userID', onDelete: 'cascade' })
DBTweet.belongsTo(DBUser, { as: 'Users', foreignKey: 'userID', onDelete: 'cascade' })
DBUser.hasMany(DBFollower, { as: 'followingUserIDAlias', foreignKey: 'followingUserID', onDelete: 'cascade' })
DBFollower.belongsTo(DBUser, { as: 'followingUserIDAlias', foreignKey: 'followingUserID', onDelete: 'cascade' })
DBUser.hasMany(DBFollower, { as: 'followerUserIDAlias', foreignKey: 'followerUserID', onDelete: 'cascade' })
DBFollower.belongsTo(DBUser, { as: 'followerUserIDAlias', foreignKey: 'followerUserID', onDelete: 'cascade' })
Related
I have 4 tables "User", "Teacher", "Address", "Subjects" the User table have connection to Teacher table (userId field) and the Teacher table have connection to "Address", and "Subjects" (teacherId)
what I want is to map all users that has a data of teacher, address and subjects, my problem is I cant connect the address and subjects table to users
this is my current code
async getUsersTeacherInfo(){
let user = await Database.getConnection().models.User
let teacher = await Database.getConnection().models.Teacher
let address = await Database.getConnection().models.Address
let subjects = await Database.getConnection().models.Subjects
user.hasOne(teacher, { foreignKey: 'userId', sourceKey: '_id' })
user.belongsTo(address, { foreignKey: 'teacherId', sourceKey: '_id' })
user.belongsTo(subjects, { foreignKey: 'teacherId', sourceKey: '_id' })
user = await Database.getConnection().models.User.findAll({
attributes:[....,],
include:[
{ model: Teacher, attributes: ['status', 'Teacher','_id'] },
{ model: Address, attributes: [....,], paranoid: false, required: false},
{ model: Subjects, attributes: [....,], paranoid: false, required: false},
]
})
}
I've tried also this
async getUsersTeacherInfo(){
let user = await Database.getConnection().models.User
let teacher = await Database.getConnection().models.Teacher
let address = await Database.getConnection().models.Address
let subjects = await Database.getConnection().models.Subjects
user.hasOne(teacher, { foreignKey: 'userId', sourceKey: '_id' })
user.belongsTo(address, { foreignKey: 'teacherId', sourceKey: '_id' })
user.belongsTo(subjects, { foreignKey: 'teacherId', sourceKey: '_id' })
user = await Database.getConnection().models.User.findAll({
attributes:[....,],
include:[
{ model: Teacher, attributes: ['status', 'Teacher','_id'],
include:[
{ model: Address, attributes: [....,], paranoid: false, required: false},
{ model: Subjects, attributes: [....,], paranoid: false, required: false},
]}
]
})
}
I have two models, Post and PostLikes, where PostLikes.postId references Post.id. I am trying to run Post.findAll({}) where PostLike.postId = Post.id. I have tried many, many things and have been unable to get anywhere. Here is what I tried last, which shows all of the info from Post, but LikeCount is 0.
await Post.findAll({
attributes: [
"id",
"username",
"title",
"body",
"createdAt",
"updatedAt",
[sequelize.fn("COUNT", sequelize.col("PostLikes.postId")), "LikeCount"]
],
include: [
{
model: PostLike,
attributes: []
}
],
group: ["Post.id"]
})
Edit: As requested, here are my model defs.
Post:
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define(
"Post",
{
title: DataTypes.STRING,
body: DataTypes.TEXT,
userId: DataTypes.INTEGER,
username: DataTypes.STRING
},
{}
);
Post.associate = function(models) {
Post.belongsTo(models.User, {
foreignKey: "username",
onDelete: "cascade"
});
Post.belongsTo(models.User, {
foreignKey: "userId",
onDelete: "cascade"
});
Post.hasMany(models.Comment, { foreignKey: "id" });
Post.hasMany(models.PostLike, { foreignKey: "id" });
};
return Post;
};
PostLike:
module.exports = (sequelize, DataTypes) => {
const PostLike = sequelize.define(
"PostLike",
{
liked: DataTypes.BOOLEAN,
userId: DataTypes.INTEGER,
postId: DataTypes.INTEGER
},
{}
);
PostLike.associate = function(models) {
PostLike.belongsTo(models.Post, {
foreignKey: "postId",
onDelete: "cascade"
});
PostLike.belongsTo(models.User, {
foreignKey: "userId",
onDelete: "cascade"
});
};
return PostLike;
};
So there seems to be something wrong with this setup, i never setup my associations this way(sequelize is very confusing and the docs seem to be inconsistent with their examples), so it's hard to tell. But i've played with your models, and i was getting some constraint error, when i was trying to add more than one PostLike. I changed it a bit, and got it to work( i removed the user references, being that they are irrelevant for the problem here):
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define(
"Post",
{
title: DataTypes.STRING,
body: DataTypes.TEXT,
userId: DataTypes.INTEGER,
username: DataTypes.STRING
},
{}
);
Post.associate = function (models) {
Post.hasMany(models.PostLike);
};
return Post;
};
module.exports = (sequelize, DataTypes) => {
const PostLike = sequelize.define(
"PostLike",
{
liked: DataTypes.BOOLEAN,
userId: DataTypes.INTEGER,
},
{}
);
PostLike.associate = function(models) {//
PostLike.belongsTo(models.Post);
};
return PostLike;
};
After inserting one post, and two postLikes, this is the result:
I have model Arhive
const Archive = sequelize.define('Archive', {
date: DataTypes.STRING,
}, {});
Archive.associate = function(models) {
Archive.hasMany(models.Video, {
foreignKey: 'ArchiveId',
onDelete: 'CASCADE',
as: 'video'
});
Archive.hasMany(models.Photo, {
foreignKey: 'ArchiveId',
onDelete: 'CASCADE'
});
};
return Archive;
};
and model Video
const Video = sequelize.define('Video', {
link: DataTypes.STRING,
pick: DataTypes.STRING,
date: DataTypes.STRING,
}, {});
Video.associate = function(models) {
Video.belongsTo(models.Archive, {
foreignKey: 'ArchiveId',
onDelete: 'CASCADE',
});
// associations can be defined here
};
return Video;
I do a search
models.Archive.findAll({
raw:true,
attributes: ['id'],
include: [{// Notice `include` takes an ARRAY
model: models.Video,
as:'video',
required:true,
attributes: ['id'],
}]
})
.then(archive => console.log(archive))
.catch(console.error)
I get unexpected
[ { id: 1, 'video.id': 1 }, { id: 1, 'video.id': 2 } ]
How to get one parent object with a child nested array ?
An example of the object to get
[ { id: 1, video[id:1,id:2] } ]
Is it possible to get a similar result with Sequelize?
All you need to do is remove raw:true from your query.
models.Archive.findAll({
// raw: true, // <------- REMOVE THIS
attributes: ['id'],
include: [{ // Notice `include` takes an ARRAY
model: models.Video,
as: 'video',
required: true,
attributes: ['id'],
}]
})
.then(archive => console.log(archive))
.catch(console.error)
It generates this kind of output while using it for nested levels with raw:true.
I have the following tables:
User
Event
RSVPs
User has 1:M relationship with Event
User has 1:M relationship with RSVPs
Event has 1:M relationship with RSVPs
When fetching Events, I would like to include RSVPs and for RSVPs I would like to include User.
Associations:
User
tableName: 'Users',
classMethods: {
associate: function (models) {
User.hasMany(models.Event, {
as: 'events',
foreignKey: 'user_id'
})
User.hasMany(models.RSVPs, {
as: 'rsvps',
foreignKey: 'user_id'
})
}
},
Event
tableName: 'Events',
classMethods: {
associate: function (models) {
Event.belongsTo(models.User, {
foreignKey: {
name: 'owner_id',
allowedNull: false,
}
}),
Event.belongsTo(models.User, {
foreignKey: {
name: 'host_id',
allowedNull: true,
}
}),
Event.hasMany(models.RSVPs, {
as: 'rsvps',
foreignKey: 'event_id'
})
}
}
RSVP
tableName: 'RSVPs',
classMethods: {
associate: function (models) {
Rsvp.belongsTo(models.User, {
foreignKey: {
name: 'user_id',
allowedNull: false,
} }),
Rsvp.belongsTo(models.Event, {
foreignKey: {
name: 'event_id',
allowedNull: false,
}
})
}
},
Attempting to fetch:
db.Event.findAll({
where: {
id: eventIds
},
order: [['updatedAt', 'ASC']],
limit: pagingLimit + 1,
include: [{
model: db.RSVPs,
as: 'rsvps',
include: [{
model: db.User,
as: 'user_id',
include: [{
model: db.AppCommon,
as: 'app_common'
}],
}]
}, {
model: db.tasks,
as: 'tasks',
}]
}).then(events => {
//Do Something
}
I didn't include association code from Tasks and AppCommon b/c I didn't think they are relevant. I can update the question, if needed.
Problem:
When I fetch Event with .findAll code above, I get the following message:
Express listening on port 3000!
Unhandled rejection Error: User (user_id) is not associated to RSVPs!
I am hoping to fetch Event that returns a Task and RSVPobject -- within that RSVP object there is a User object, and within that User Object there is a AppCommon object. What am I doing wrong?
Update
I tried to simplify the query to:
db.RSVPs.findAll({
where: {
user_id: req.user_id
},
include: [{
model: db.User,
as: 'user'
}]
}).then(rsvps => {
)}
Associations:
tableName: 'RSVPs',
classMethods: {
associate: function (models) {
Rsvp.belongsTo(models.Event, {
foreignKey: {
name: 'event_id',
allowedNull: false,
}
}),
Rsvp.belongsTo(models.User, {
foreignKey: 'user_id'
})
}
},
But this is failing with "Error: User (user) is not associated to RSVPs!"
I'm trying to get the value and returns postgres me that this column does not exist. I am not able to deal in any way.
"column Group.participant.id does not exist"
relationship:
User.belongsToMany(models.group, { as: 'Member', through: { model: models.participant, unique: false}, foreignKey: 'userId', constraints: false});
Group.belongsToMany(models.user, { as: 'Group', through: { model: models.participant, unique: false}, foreignKey: 'groupId', constraints: false });
Participant.belongsTo(models.user, {
foreignKey: "userId", as: "Member"
});
Participant.belongsTo(models.group, {
foreignKey: "groupId", as: "Group"
});
Query/Sequelizejs:
const User = app.db_connect.postgres.models.user;
Group.findAll({
include: [
{ model: User,
as: 'Group',
where: {
"participant.id": idUser
}
// attributes: ['name']
}
]})
.then(result => res.json(result))
.catch(error => {
res.status(412).json({msg: error.message});
});
});
Query generate:
Executing (default): SELECT "group"."id", "group"."name", "group"."isMain", "group"."privacy", "group"."description", "group"."img", "group"."createdAt", "group"."updatedAt", "group"."destroyTime", "group"."categoryId", "Group"."id" AS "Group.id", "Group"."name" AS "Group.name", "Group"."birthday" AS "Group.birthday", "Group"."cpf" AS "Group.cpf", "Group"."email" AS "Group.email", "Group"."img" AS "Group.img", "Group"."status" AS "Group.status", "Group"."phone" AS "Group.phone", "Group"."cellPhone" AS "Group.cellPhone", "Group"."nickName" AS "Group.nickName", "Group"."password" AS "Group.password", "Group"."found" AS "Group.found", "Group"."createdAt" AS "Group.createdAt", "Group"."updatedAt" AS "Group.updatedAt", "Group"."destroyTime" AS "Group.destroyTime", "Group.participant"."id" AS "Group.participant.id", "Group.participant"."function" AS "Group.participant.function", "Group.participant"."createdAt" AS "Group.participant.createdAt", "Group.participant"."updatedAt" AS "Group.participant.updatedAt", "Group.participant"."groupId" AS "Group.participant.groupId", "Group.participant"."userId" AS "Group.participant.userId" FROM "groups" AS "group" INNER JOIN ("participants" AS "Group.participant" INNER JOIN "users" AS "Group" ON "Group"."id" = "Group.participant"."userId") ON "group"."id" = "Group.participant"."groupId" AND ("Group"."destroyTime" IS NULL AND "Group"."participant.id" = 1) WHERE "group"."destroyTime" IS NULL;
Returns without the where: Pastebin
Use just id in where, because in include section you work with a columns of specific model
Group.findAll({
include: [{ model: User, as: 'Group',
where: {
"id": idUser
}
}]})