How to count nested elements inside a model? - javascript

I'm building an app with Express, Postgres as db and Sequelize as ORM.
This is the response I get:
{
"user": {
"user_name": "John",
"post": [
{
"id": 1,
"created_at": "2018-04-16T22:52:59.054Z",
"post_titles": [
{
"title_id": 3571
},
{
"title_id": 3570
},
{
"title_id": 3569
}
]
},
],
}
}
How can I count how many titles there are in the post?
I have 4 models:
User, hasMany Posts
Post, has many Titles through PostTitles
Title
PostTitle
This is my query:
User.findOne({
where: { id: req.params.id },
attributes: ['id', 'user_name'],
include: [
{ model: Post,
attributes: ['id', 'created_at'],
include: {
model: PostTitles,
attributes: ['title_id']
}
}
]
})
Thanks!

You can use count function .
User.findOne({
where: { id: req.params.id },
attributes: ['id', 'user_name'],
include: [
{ model: Post,
attributes: ['id', 'created_at'],
include: {
model: PostTitles,
attributes: ['title_id',[Sequelize.literal('COUNT(DISTINCT(title_id))'), 'totalcount']]
}
}
]
})

Related

Sequelize include nested column: Unknown column in 'where clause'

I am trying to use the Sequelize ORM's feature that allows referring the nested column from the included Models (See Sequelize Docs: Complex where clauses at the top-level). In the docs it states that, I can use $nested.column$ syntax.
The following is what I was trying to do:
let where = { memberId };
if (req.query.search) {
const like = { [Op.like]: `%${req.query.search}%` };
where = {
...where,
[Op.or]: [
{ '$bookItem.serial$': like },
{ '$bookItem.book.name$': like },
{ '$bookItem.book.ISBNCode$': like },
],
};
}
const options = {
where,
include: [
{
model: models.BookItem,
as: 'bookItem',
required: false,
include: [
{
model: models.Book,
as: 'book',
attributes,
required: false,
},
],
},
],
});
const transactions = await models.Borrow.findAll(options);
However, for the code above, I am getting the following error:
"Unknown column 'bookItem.serial' in 'where clause'"
What am I missing?
Full DB Schema: https://dbdiagram.io/d/5e08b6aaedf08a25543f79cb
Is bookitem a Table? Or a Database?
bookItem.serial either represents db.tbl or tbl.column
bookItem.book.name can only represent db.tbl.column
Since bookItem seems to be a database name, then serial must be a table name. At that point, "tablename LIKE ..." is a syntax error.
In your linked documentation books has no name column, change $bookItem.book.name$ to $bookItem.book.title$, and try adding right: true below required: false to create an inner join.
I have corrected this error on my side. Initially, I am writing this query
but now I have rearranged the query and it works
WRONG QUERY
let where = {
[op.and]: [
{ id: partner_id },
{ [op.or]: [
{ '$customers.customer_name$': { [op.like]: '%' + query + '%'} },
{ '$customers.email$': { [op.like]: '%' + query + '%'} },
]},
],
};
// const where = {
// id: partner_id
// }
return await this.deliveryBoys.findOne({
attributes: [
['id', 'partner_id'],
'delivery_boy_name',
'email',
'profile_picture',
'phone_number',
'fcm_token',
],
include: [
{
model: this.customers,
as: 'customers',
attributes: ['id', 'customer_name', 'email', 'profile_picture', 'phone_number'],
require: true,
where: {
customer_name: {
[op.like]: '%' + query + '%'
}
},
include: [
{
model: this.company,
as: 'company',
},
{
model: this.address,
as: 'address',
required: false,
where: {
status: 1
}
}
]
},
],
where,
});
FINAL WORKING QUERY
let where = {
[op.and]: [
{ '$deliveryBoys.id$': partner_id },
{ [op.or]: [
{ '$customers.email$': { [op.like]: '%' + query + '%'} },
{ '$customers.customer_name$': { [op.like]: '%' + query + '%'} },
{ '$customers.phone_number$': { [op.like]: '%' + query + '%'} },
{ '$company.name$': { [op.like]: '%' + query + '%'} },
]},
],
};
return await this.customers.findAll({
attributes: ['id', 'customer_name', 'email', 'profile_picture', 'phone_number'],
include:[
{
model: this.deliveryBoys,
as: 'deliveryBoys',
attributes: ['id','delivery_boy_name','phone_number','email','profile_picture','status',],
where:{
id: partner_id
}
},
{
model: this.company,
as: 'company',
},
{
model: this.address,
as: 'address',
required: false,
where: {
status: 1
}
}
],
where
});

Mongo node js query implicit $and

It should only update and return results that have match on the request data.
it should be not mutually exclusive (i.e. if one query does not match then do not return result results)
is using implicit $and a solution to that ?
Query
keystone.list('Vehicle').model.update({ $or: [{ Body: { $in: req.body.data[0].body } }, { Model: { $in: req.body.data[0].model } }, { Make: { $in: req.body.data[0].make } }, { Year: { $in: req.body.data[0].year } }] }, {
$set: {
'Summer_Sale_Event': req.body.summer_sale_value
}
}, {
'multi': true
}).exec(function (err, result) {
});
Request data
Request : [ { body: [ 'Convertible' ],
make: [ 'Chevrolet' ],
year: [ '2005' ],
model: [ 'Corvette' ] } ]
$or means that only one of the condition have to be true.
You should be using $and instead.

Sequelize many-to-many self association

I am trying to create a model Users with many-to-many association to itself to allow users to follow another users. In one query I want to retrieve the Users followed by the current user; in another query I want to retrieve the people that follows the current user.
This is my Users model:
module.exports = (sequelize, Sequelize) => {
const Users = sequelize.define(
'Users',
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
},
},
);
Users.associate = function(models) {
Users.belongsToMany(Users, { as: 'following', through: models.UsersUsers });
};
return Users;
};
I declare UsersUsers, just in case I need to add any field there:
module.exports = (sequelize, Sequelize) => {
const UsersUsers = sequelize.define(
'UsersUsers',
{}
);
UsersUsers.associate = function(models) {};
return UsersUsers;
};
Then I query Users as:
models.Users.findOne({
where: {
id: req.params.id,
},
include: [
{
model: models.Users,
as: 'following',
},
],
})
.then((results) => {
return res.send({
User: results,
});
})
.catch((error) => {
return res.send(String(error));
});
And I get this result:
{
"User": {
"id": 1,
"name": "User1",
"following": [
{
"id": 2,
"name": "User2",
"UsersUsers": {
"UserId": 1,
"followingId": 2
}
},
{
"id": 3,
"name": "User3",
"UsersUsers": {
"UserId": 1,
"followingId": 3
}
},
{
"id": 4,
"name": "User4",
"UsersUsers": {
"UserId": 1,
"followingId": 4
}
}
]
}
}
Now the questions:
In my current query, how do I exclude "UsersUsers" from the result? attributes: { exclude: ['UsersUsers'] } did not work…
How do I create a query to retrieve the current user with the users that follows him instead of the users followed by him?
Thanks!
--
EDIT:
The solution for the question 1. is to add through: { attributes: [] } to the included model:
models.Users.findOne({
where: {
id: req.params.id,
},
include: [
{
model: models.Users,
as: 'following',
through: {
attributes: [],
},
},
],
})
.then((results) => {
return res.send({
User: results,
});
})
.catch((error) => {
return res.send(String(error));
});
Still pending question 2!
Users.findAll({
include: [
{
model: models.Users,
as: 'following',
through: {
attributes: [],
},
},
],
where : {
id : [connection.literal(` write raw sql query to get followingId here`)]
}
})
.then(result => {
res.json(result);
}).catch(error=>{
res.json(error);
});
I'm not sure if this gonna work, still play around this and do let me know if this worked or if you found any solution.

Combined WHERE clause for all INCLUDEs

i want to perform this query in sequelize models:
SELECT Cou.country_id,cou.country_name, Sta.state_id, Sta.state_name, Dis.district_id,
Dis.district_name,Cit.city_id, Cit.city_name,Loc.location_id,Loc.location_name,Sub_Loc.sub_location_id,Sub_Loc.sub_location_name,Prop.property_id,Prop.property_name,Prop.hp_builders_id,
Bud.builders_id,Bud.builders_name
FROM hp_country Cou
INNER JOIN hp_state Sta ON Cou.country_id = Sta.hp_country_id
INNER JOIN hp_district Dis ON Sta.state_id = Dis.hp_state_id
INNER JOIN hp_city Cit ON Dis.district_id = Cit.hp_district_id
INNER JOIN hp_location Loc ON Cit.city_id = Loc.hp_city_id
INNER JOIN hp_sub_location Sub_Loc ON Loc.location_id = Sub_Loc.hp_location_id
INNER JOIN hp_property Prop ON Sub_Loc.sub_location_id=Prop.hp_sub_location_id
LEFT JOIN hp_builders Bud ON Prop.hp_builders_id=Bud.builders_id
where (Cou.country_status=1 AND Sta.state_status=1 AND Cou.country_id=1)
AND (Dis.district_name LIKE '%ky%' OR Cit.city_name LIKE '%ky%' OR Loc.location_name LIKE '%ky%' OR Sub_Loc.sub_location_name LIKE '%ky%' OR Prop.property_name LIKE '%ky%')
I tried to write in this manner but i did not achieved my target query :
Included more nested models because of all are inner joins and i tried with required is true in include box.how to do [OR] condition for columns which is in different tables
hp_country.findAll({
attributes: ['country_id', 'country_name'],
where: {
country_status: 1,
country_id: 1
},
include: [{
model: hp_state,
attributes: ['state_id', 'state_name'],
where: {
state_status: 1,
},
include:[{
model: hp_districts,
attributes: ['district_id', 'district_name'],
where: {
district_status: 1
},
include:[{
model: hp_city,
attributes: ['city_id', 'city_name'],
where: {
city_status: 1,
city_name :{
$like: '%ma%'
}
},
include:[{
model: hp_location,
attributes: ['location_id', 'location_name'],
where: {
location_status: 1,
location_name :{
$like: '%ma%'
}
},
include:[{
model: hp_sub_location,
attributes: ['sub_location_id', 'sub_location_name'],
where: {
sub_location_status: 1,
sub_location_name :{
$like: '%ma%'
}
}
}]
}]
}]
}]
}]
})
I tried to fix your query, but didn't test it. If you face any problem just notify me:
hp_country.findAll({
attributes: ['country_id', 'country_name'],
where: {
//main AND condition
$and: [
//first joint condition
{
$and: [
{ country_status: 1 },
{ country_id: 1 },
Sequelize.literal("Sta.state_status = 1") //I put 'state_status' here because it was a joint condition to be true
],
},
//second joint condition
{
$or: [
Sequelize.literal("Dis.district_name LIKE '%ky%'"),
Sequelize.literal("Cit.city_name LIKE '%ky%'"),
Sequelize.literal("Loc.location_name LIKE '%ky%' "),
Sequelize.literal("Sub_Loc.sub_location_name LIKE '%ky%'"),
Sequelize.literal("Prop.property_name LIKE '%ky%'")
]
}
]
},
include: [
{
model: hp_state,
attributes: ['state_id', 'state_name']
},
{
model: hp_districts,
attributes: ['district_id', 'district_name']
},
{
model: hp_city,
attributes: ['city_id', 'city_name']
},
{
model: hp_location,
attributes: ['location_id', 'location_name']
},
{
model: hp_sub_location,
attributes: ['sub_location_id', 'sub_location_name']
}
]
})

querying on where association in sequelize?

where clause use in sequelize in inner joins.
My query is
SELECT Cou.country_id,cou.country_name, Sta.state_id, Sta.state_name
FROM hp_country Cou
INNER JOIN hp_state Sta ON Cou.country_id = Sta.hp_country_id
WHERE (Cou.country_status=1 AND Sta.state_status=1 AND Cou.country_id=1)
AND (Sta.state_name LIKE '%ta%');
I wrote in sequelize code is
hp_country.findAll({
where: {
'$hp_state.state_status$': 1
},
include: [
{model: hp_state}
]
})
The error it's producing is:
SELECT `hp_country`.`country_id`, `hp_country`.`country_name`, `hp_country`.`country_status`, `hp_country`.`created_date`, `hp_country`.`update_date` FROM `hp_country` AS `hp_country` WHERE `hp_state`.`state_status` = 1;
Unhandled rejection SequelizeDatabaseError: ER_BAD_FIELD_ERROR: Unknown column 'hp_state.state_status' in 'where clause'
Your Sequelize code should look like:
hp_country.findAll({
attributes: ['country_id', 'country_name'],
where: {
country_status: 1,
country_id: 1
},
include: [{
model: hp_state,
attributes: ['state_id', 'state_name'],
where: {
state_status: 1,
state_name: {
$like: '%ta%'
}
}
}]
});
To select only some attributes, you can use the attributes option.
where clause should be moved inside the include statement because the condition you use relates to the hp_state model.
hp_country.findAll({
where: {
//main AND condition
$and: [
//first joint condition
{
$and: [
{ country_status: 1 },
{ country_id: country_id },
Sequelize.literal("hp_states.state_status = 1"),
Sequelize.literal("`hp_states.hp_districts`.`district_status`=1"),
Sequelize.literal("`hp_states.hp_districts.hp_cities`.`city_status`=1"),
Sequelize.literal("`hp_states.hp_districts.hp_cities.hp_locations`.`location_status`=1"),
Sequelize.literal("`hp_states.hp_districts.hp_cities.hp_locations.hp_sub_locations`.`sub_location_status`=1"),
Sequelize.literal("`hp_states.hp_districts.hp_cities`.`city_name` LIKE '%"+city+"%'")
]
},
{
$or: [
Sequelize.literal("`hp_states.hp_districts.hp_cities.hp_locations`.`location_name` LIKE '%"+query+"%'"),
Sequelize.literal("`hp_states.hp_districts.hp_cities.hp_locations.hp_sub_locations`.`sub_location_name` LIKE '%"+query+"%'"),
Sequelize.literal("`hp_states.hp_districts.hp_cities.hp_locations.hp_sub_locations.hp_property`.`property_name` LIKE '%"+query+"%'"),
Sequelize.literal("`hp_states.hp_districts.hp_cities.hp_locations.hp_sub_locations.hp_property.hp_builder`.`builders_name` LIKE '%"+query+"%'")
]
}
]
},
attributes: ['country_id', 'country_name'],
required:true,
include: [
{
model: hp_state,
attributes: ['state_id', 'state_name'],
required:true,
include: [
{
model: hp_district,
attributes: ['district_id', 'district_name'],
required:true,
include: [
{
model: hp_city,
attributes: ['city_id', 'city_name'],
required:true,
include: [
{
model: hp_location,
attributes: ['location_id', 'location_name'],
required:true,
include: [
{
model: hp_sub_location,
attributes: ['sub_location_id', 'sub_location_name'],
required:true,
include: [
{
model: hp_property,
attributes: ['property_id', 'property_name'],
required: true,
include: [
{
model:hp_builders,
attributes: ['builders_id', 'builders_name'],
required: true
}
]
}
]
}]
}]
}]
}
]
}
]
})

Categories

Resources