sequelize where on assosiated model - mysql

I have three Models User, Group, UserGroup. User and Group have many to many relations through UserGroup model. I want to get groups with all of there group members But also want only those groups that a user is a member of. Here is my sequelize query.
Group.findAll({
include: ['members'],
where: {
'$members.id$': user_id
}
});
With where condition in the above code the groups gets filtered according to user_id. ie. It returns groups related to User model with id equals to user_id. But this query is not giving all the members. it only returns one user that has id equals to user_id. That means the "where" condition is not only filtering the groups, it is also filtering the group members.
Here are my associations
Group.hasMany(UserGroup, {as: {singular: 'usergroup', plural: 'usergroups'}, foreignKey: 'group_id'});
Group.belongsToMany(User, {as: {singular: 'member', plural: 'members'}, through: UserGroup});
UserGroup.belongsTo(User, {as: 'member', foreignKey: 'user_id'});
UserGroup.belongsTo(Group, {as: 'group', foreignKey: 'group_id'});

Can you try it and let me know :)
Group.findAll({
include: ['members'],
where:{
id: {
$in: sequelize.literal(`(select distinct group_id from usergroup where user_id = ${user_id})`)
}
}
})
.then(results => {
console.log(results);
})
.catch(err => {
console.log('err', err);
});

Related

Sequelize: find count of 3 level associated model entries

I have a products database structure as follows:
Categories > Sub categories > Child categories > Products
the respective table names in mySql database are:
categories, subCategories, childCategories and products
My model definitions are as follows:
////////////////// DEFINING ASSOCIATIONS /////////////
/******* CATEGORY - SUBCATEGORY ASSOCIATION *********/
db.category.hasMany(db.subCategory, {
foreignKey: 'categoryId',
sourceKey: 'id',
});
db.subCategory.belongsTo(db.category, {
foreignKey: 'categoryId',
targetKey: 'id',
});
/******* SUBCATEGORY - CHILDCATEGORY ASSOCIATION *********/
db.subCategory.hasMany(db.childCategory, {
foreignKey: 'subCategoryId',
sourceKey: 'id',
});
db.childCategory.belongsTo(db.subCategory, {
foreignKey: 'subCategoryId',
targetKey: 'id',
});
/******* CHILDCATEGORY - PRODUCT ASSOCIATION *********/
db.childCategory.hasMany(db.product, {
foreignKey: 'childCategoryId',
sourceKey: 'id',
});
db.product.belongsTo(db.childCategory, {
foreignKey: 'childCategoryId',
targetKey: 'id',
});
In my summary result, I want to share a table as follows:
For this, I tried multiple variations of the below code but am unable to produce the required result.
My current code to achieve the above result:
exports.getAllCategoriesSummary = async (req, res) => {
const { page, size, search } = req.query;
console.log(page, size, search);
try {
const totalCategories = await Category.count();
// get categories and count of included subCategories, childCategories and products
const [rows, fields] = await mysqlConnPool.promise().execute(
`SELECT c.id, c.name, COUNT(DISTINCT(s.id)) AS subCategories,
COUNT(DISTINCT(ch.id)) AS childCategories, COUNT(p.id) AS products
FROM categories c
LEFT JOIN subCategories s ON c.id = s.categoryId
LEFT JOIN childCategories ch ON s.id = ch.subCategoryId
LEFT JOIN products p ON ch.id = p.childCategoryId GROUP BY c.id
ORDER BY c.id ASC LIMIT ${size} OFFSET ${page * size}
`
);
return res.status(200).json({
status: 'success',
categories: rows,
totalCategories: totalCategories,
});
} catch (error) {
return res.status(500).json({
status: 'error',
message: error.message,
});
}
};
Requesting help to produce the needed result using sequelize.

Getting wrong query generated by Sequelize Assocation

I have two table. One is Order and second one is OrderStatus.
In the orders table order_status_code is foreignKey that references on id to the OrderStatus table.
I have below model association definition.
Order.associate = function(models) {
// associations can be defined here
Order.hasOne(models.OrderItem,{foreignKey: "order_id"}),
Order.hasOne(models.OrderStatus, {foreignKey: "order_status_code"})
};
I am getting below error:
Unknown column 'OrderStatus.order_status_code' in 'field list
when I try to eager loading the OrderStatus.
const orders = await Order.findAll({
where: filter,
include: {
model: OrderStatus
}
})
Below is the query that is being shown on the console.
SELECT `Order`.`id`, `Order`.`buyer_id`, `Order`.`order_status_code`, `Order`.`order_detail`, `Order`.`order_date`, `Order`.`order_number`, `Order`.`created_at`, `Order`.`updated_at`, `OrderStatus`.`id` AS `OrderStatus.id`, `OrderStatus`.`order_status_code` AS `OrderStatus.order_status_code`, `OrderStatus`.`status` AS `OrderStatus.status`, `OrderStatus`.`created_at` AS `OrderStatus.created_at`, `OrderStatus`.`updated_at` AS `OrderStatus.updated_at` FROM `Orders` AS `Order` LEFT OUTER JOIN `OrderStatuses` AS `OrderStatus` ON `Order`.`order_status_code` = `OrderStatus`.`id` WHERE `Order`.`buyer_id` = 23;
I don't know why it is selecting OrderStatus.order_status_code
I fixed it by defining attributes to select from the included model and It fixed the problem for now.
const orders = await Order.findAll({
where: filter,
include: {
model: OrderStatus,
attributes:["status"]
}
})

Query records that does not have an entry in another table using Sequelize include clause

Given Users table and Ratings table
How do I query all user records from Users table that does not have any rating record in Ratings table using Sequelize include clause
Note: Sequelize version 5.x
Thanks in advance
You can do this in two ways depending on how your models are defined.
1. Get all Users along with Ratings by using Sequelize Eager Loading. Then filter where user does not have any ratings.
const users = Users.findAll({
include: [Ratings]
});
const filteredUsers = users.filter(user => user.ratings.length === 0);
2. Get all userIds from the Ratings table and then pass these userIds to the where clause using the notIn Sequelize operator
const ratings = Ratings.findAll({
attributes: ["userId"],
group: ["userId"]
});
const userIds = ratings.map(rating => rating.userId);
const filteredUsers = Users.findAll({
where: {
userId: { [Op.notIn]: userIds }
}
});
Try incorporating a sequelize literal in the where clause:
const ratings = Ratings.findAll({
attributes: ["userId"],
group: ["userId"],
where: {
$and: [
sequelize.literal(`NOT EXISTS (
SELECT 1 FROM Ratings r
WHERE r.userId = User.id
)`),
],
},
});
Assuming you have a relationship between Users and Ratings in your models, this can be accomplished in a single query by using a left outer join followed by a filter on the client side.
In your model definition:
Users.hasMany(Ratings, { foreignKey: 'user_id' });
Ratings.belongsTo(Users, { foreignKey: 'user_id' });
In your query:
const users = await Users.findAll({
include: [
{
model: Ratings,
required: false // left outer join
}
]
});
const usersWithoutRatings = users.filter(u => u.user_ratings.length === 0);

NODEJS - Perform INNER JOIN sequelize

I want to perform an INNER JOIN using sequelize and Node. The actual SQL query looks like this:
SELECT b.id, b.title, b.author, b.image_url, s.novel_status AS status, g.genre
FROM novels b
INNER JOIN genres g
ON b.genre = g.id
INNER JOIN novel_statuses s
ON b.status = s.id
Which gives the following response:
Using sequelize as my ORM, I have tried to accomplish the above like this:
getNovel: (req, res) => {
novelModel.hasMany(statusModel, {
foreignKey: 'id'
});
statusModel.belongsTo(novelModel, {
foreignKey: 'id'
});
novelModel.hasMany(genreModel, {
foreignKey: 'id'
});
genreModel.belongsTo(novelModel, {
foreignKey: 'id'
});
novelModel
.findAll({
include: [
{
model: genreModel,
required: true,
attributes: ['genre']
},
{
model: statusModel,
required: true,
attributes: ['novel_status']
}
]
})
.then(result => res.json(result))
.catch(err => res.json(err));
},
But then the response is different, i.e. as below:
My DB:
I have tried to search for answers, but without any luck.
You should give the name of the Model Framework you use.

Bookshelf(knex) - belongsToMany relation not working

I have been trying to setup a relation between Posts and Tags using belongsToMany relation (Bookshelf). Here is my code:
db.js
const Post = bookshelf.Model.extend({
tableName: 'posts',
hasTimestamps: true,
tags: function(){
return this.belongsToMany(Tag)
}
})
const Tag = bookshelf.Model.extend({
tableName: 'tags',
posts: function(){
return this.belongsToMany(Post)
}
})
// Pivot table
const PostTag = bookshelf.Model.extend({
tableName: 'posts_tags',
post: function(){
return this.belongsTo(Post)
},
tag: function(){
return this.belongsTo(Tag)
}
})
Get route is:
.get('/:id', (req, res, next) => {
db
.Post
.where('id', req.params.id)
.fetch({widthRelated: ['tags'], require:true})
.then((data)=> {
return res.json({data, ralation: data.related('tags').toJSON()})
})
})
I have already added a table 'posts_tags' in database and all the database is seeded including this pivot table. So when I query in route, the relationship query does not even initiate. knex debug: sql: 'select posts.* from posts where id = ? limit ?'
Tables
posts - id title text created_at updated_at
tags - id name created_at updated_at
posts_tags - id post_id tag_id created_at updated_at
Is there any mistake(s) in code?
Sorry for this Post - I had just the typo:
.fetch({widthRelated: ['tags'], require:true})
widthRelated = withRelated!!!!!!