Geting value of a relationship in sequelize js - javascript

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

Related

How can I count inside nested associations in Sequelize?

I try to count product reviews in nested associations. With the following query.
const user = await User.findOne({
where: {
id: req.query.user
},
attributes: ["id", "name"],
include: [
{
model: Category,
as: "interests",
attributes: ["category_name"],
through: {
attributes: []
},
include: [
{
model: Product,
as: "products",
attributes: {
include: [
[
// How to count product_reviews here?
sequelize.literal(`
(SELECT COUNT(*) FROM product_reviews WHERE productId = Product.id)
`),
"num_reviews"
]
]
},
include: [
{
model: User,
as: "userReviews",
attributes: []
}
]
}
]
}
]
});
In the model definitions I have a belongsTo/haveMany association set up e.g.:
Inside my models
// User model
User.belongsToMany(models.Category, {
through: "user_categories",
as: "interests",
foreignKey: "userId"
});
User.belongsToMany(models.Product, {
through: "user_reviews",
as: "reviews",
foreignKey: "userId"
});
// Category model
Category.hasMany(models.Product, {
foreignKey: "categoryId",
as: "products"
});
// Product model
Product.belongsToMany(models.User, {
through: "product_reviews",
as: "userReviews",
foreignKey: "productId"
});
// Product_reviews model
product_review.belongsTo(models.User, { foreignKey: "userId" });
product_review.belongsTo(models.Product, { foreignKey: "productId" });
How to count product reviews?
Here the result I want.
{
"id": 1,
"name": "John Doe",
"interests": [
{
"category_name": "Toys",
"products": [
{
"id": 1,
"name": "Lorem Ipsum",
"num_reviews": 20 // I need to count # of reviews here
},
...
]
}
]
}
Can anyone explain how to get counting inside nested associated in this case?
I guess you are on the right track and you just need to modify the way of constructing Sequelize literal for reviews count as follows -
sequelize.literal(`
(SELECT COUNT(*) FROM product_reviews WHERE productId = \`products\`.\`id\`)
`)

How to specify foreign key in association query

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

How to get one parent object with a child nested array with association while using 'include' option to query in 'Sequelize'?

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.

Sequelize Many to Many Query Issue

So, I have an existing MySQL database that I'm trying to connect to with Sequelize in Node that has a products table, a categories table and a categories_products table. What I want to do is return products, with each product containing all of the categories it belongs to. Here's what I've got:
// Declare Product Model
const Product = sequelize.define('products', {
name: Sequelize.STRING,
description: Sequelize.STRING,
single_price: Sequelize.BOOLEAN,
oz_price: Sequelize.FLOAT,
half_price: Sequelize.FLOAT,
quarter_price: Sequelize.FLOAT,
eigth_price: Sequelize.FLOAT,
gram_price: Sequelize.FLOAT,
unit_price: Sequelize.FLOAT
},
{
underscored: true
});
// Declare Category Model
const Category = sequelize.define('categories', {
name: Sequelize.STRING,
parent_id: Sequelize.INTEGER,
picture_file_name: Sequelize.STRING
},
{
underscored: true
});
// Join Table
const ProductCategory = sequelize.define('categories_products', {
product_id: Sequelize.INTEGER,
category_id: Sequelize.INTEGER,
}, {
timestamps: false,
underscored: true
});
// Do this because there is no id column on ProductCategory table
ProductCategory.removeAttribute('id');
Category.hasMany(Category, { as: 'children', foreignKey: 'parent_id' });
ProductCategory.belongsTo(Product);
ProductCategory.belongsTo(Category);
Product.hasMany(ProductCategory);
Category.hasMany(ProductCategory);
Using this setup, I query as follows:
Product.findAll({
include: [{
model: ProductCategory,
include: [ Category ]
}],
where: { active: true },
limit: 10
}).then(prods => {
res.send(prods);
}).catch(err => {
res.status(500).send(err);
});
I get back my products and each one has an array of categories, BUT each product only shows a max of one category. I have products that should have many categories, but it only shows the first.
Am I missing something? Any help would be greatly appreciated.
I think you should use belongsToMany association here.
You can define association like this
Product.belongsToMany(Category, { through: ProductCategory, foreignKey: 'product_id' });
Category.belongsToMany(Product, { through: ProductCategory, foreignKey: 'category_id' });
and the query can be
Product.findAll({
include: [Category]
}).then((res) => {
console.log(res);
})
Though the questioner might have gotten the solution but I ran into this composite key table problem and this is the solution with code example. Notice the "through" keyword. That is what solves the association where you want to limit your findings to say a category as AbhinavD asked above. Your category id would go in the literal expression. Applies to findAll too.
const products = await Product.findAndCountAll({
include: [Category],
through: { where: { category_id: `${category_id}` } },
attributes: [
'product_id',
'name',
],
limit: limitPage,
offset: offsett,
});

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

Categories