Nodejs Op sequelize multiple relationship - javascript

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},
]}
]
})
}

Related

Sequelize Join with Count of matching id

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:

Sequelize: Fetching with include returns not associated error

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!"

Sequelize belongsToMany: TypeError: Cannot read property 'hasBrand' of undefined

I have User and Brand models.
A user can have many brands.
A brand can belong many users.
I defined another model for many-to-many associations. It named UserBrand.
// user.js
const User = sequelize.define('User', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
hasBrand: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
})
User.associate = models=> {
User.belongsToMany(models.Brand, {
through: models.UserBrand,
foreignKey: 'user',
})
}
// brand.js
Brand.belongsToMany(models.User, {
through: models.UserBrand,
foreignKey: 'brand',
})
// userBrand.js
const UserBrand = sequelize.define('UserBrand', {
status: {
type: DataTypes.INTEGER,
allowNull: false,
},
title: {
type: DataTypes.STRING,
defaultValue: '',
},
})
UserBrand.associate = models=> {
UserBrand.belongsTo(models.User, { foreignKey: 'user', targetKey: 'id' })
UserBrand.belongsTo(models.Brand, { foreignKey: 'brand', targetKey: 'id' })
}
When I run my application, it shows TypeError: Cannot read property 'hasBrand' of undefined. I can not find any relation between hasBrand and association, but remove hasBrand it works
How can I fix it in case I still want to keep hasBrand field?

Sequelize join data in tree

I have 3 models that work like a tree: Plants, Genre and family.
Each family can have a lot of genres each genre is associated to 1 family.
Same for Genre, each 1 can have a lot of plants and 1 plant can have 1 genre.
So based on that, i have this models:
Plant
"use strict";
var sequelize = require('./index');
var bcrypt = require('bcrypt-nodejs');
var User = require('./User');
module.exports = function (sequelize, DataTypes) {
var Plant = sequelize.define("Plant", {
specie: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
allowNull: true,
defaultValue: "No description for this plant yet"
},
directory: {
type: DataTypes.STRING,
allowNull: false
},
genreId: {
type: DataTypes.INTEGER,
allowNull: true
}
},
{
associate: function (models) {
Plant.hasMany(models.Foto, { foreignKey: "plantId", as: 'fotos' });
}
}
);
Genre
module.exports = function (sequelize, DataTypes) {
var Genre = sequelize.define("Genre", {
name: {
type: DataTypes.STRING,
allowNull: false
},
familyId: {
type: DataTypes.INTEGER,
allowNull: true
},
directory: {
type: DataTypes.STRING,
allowNull: false
}
},
{
associate: function (models) {
Genre.hasMany(models.Plant, { foreignKey: "genreId", as: 'plant' });
}
}
);
Family
module.exports = function (sequelize, DataTypes) {
var Family = sequelize.define("Family", {
name: {
type: DataTypes.STRING,
allowNull: false
},
directory: {
type: DataTypes.STRING,
allowNull: false
}
},
{
associate: function (models) {
Family.hasMany(models.Genre, { foreignKey: "familyId", as: 'genre' });
}
}
);
now, i do a query where i want to get all data related to the plant(genre and family) so i pass the id for the plant in the routing, via req.params.id.
after that i try to do a include so i can get the data with eager loading, because i need to get a json with all the data related to the plant.
But i can't get any data related to the other models, just with the specific plant table, any help?
Here is the controller code on the server:
specificPlant: function (req, res, next) {
Plant.findAll({
where: {
id: req.params.id,
},
include: [{ all: true }]
}).then(function (plant) {
console.log(plant);
return res.send(plant);
}).catch(function (err) {
return res.status(400).send({ message: err.stack }); //
})
}
First, define associations that will allow you to get data Plant->Genre->Family
Plant.hasMany(models.Genre, {foreignKey: "genreId", as: 'genre' });
Genre.hasMany(models.Family, { foreignKey: "familyId", as: 'family' });
Then you can query
Plant.findAll({
where: {
id: req.params.id,
},
include: [{
model: Genre,
as: 'genre',
include: [{
model: Family,
as: 'family'
}]
}]
}).then(function (plant) {
//plant
//plant.genre
//plant.genre.family
});

Geting value of a relationship in sequelize js

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
}
}]})

Categories