querying on where association in sequelize? - javascript

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

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

sequelize.literal return both the origin attribute name and the attribute after renaming

I want to rename attributes after doing join, i tried to use sequelize.literal in nodejs but it returns both the origin name and modified name. How can i remove the origin name from result?
const result = await User.findAll({
attributes: [
'name',
'id',
[Sequelize.literal('Company.name'), 'companyName'],
[Sequelize.literal('Employee.type'), 'employeeType'],
],
include: [
{ model: Company, attributes: ['name'], required: false },
{ model: Employee, attributes: ['type'], required: true },,
],
raw: true,
});
Result:
...
"companyName": "Test",
"employeeType": "Junior",
"Company.name": "Test",
"Employee.type": "Junior",
Desired Result:
...
"companyName": "Test",
"employeeType": "Junior",
I just found out a solution to this question, But i'm open to other ideas
Here's what I did and it works well with me.
const result = await User.findAll({
attributes: [
'name',
'id',
'Company.name',
[Sequelize.literal('`Company`.`name`'), 'companyName'],
'Employee.type',
[Sequelize.literal('`Employee`.`type`'), 'employeeType'],
],
include: [
{ model: Company, attributes: [], required: false },
{ model: Employee, attributes: [], required: true },,
],
raw: true,
});

How to count nested elements inside a model?

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

Sequelize conditional inclusion of where clause nodejs

I have this code, which has multiple where clause:
Time_Sheet_Details.findAll({
include: [
{
model: timesheetNotesSubcon,
required: false,
attributes:["note","file_name", "id", "working_hrs", "timestamp", "has_screenshot", "notes_category"]
},
{
model: Timesheet,
attributes:["id","leads_id","userid"],
where: {leads_id: filters.leads_id}, // Client
include:[
{
model: Lead_Info, attributes:["id","fname","lname","email","hiring_coordinator_id","status"],
where: {hiring_coordinator_id: {$in: filters.sc_id}}, // SC
include:[{
model: adminInfoSchema,
required: false,
attributes:["admin_id","admin_fname", "admin_lname", "admin_email", "signature_contact_nos", "signature_company"],
}]
},
{
model:Personal_Info,attributes:["userid","fname","lname","email"],
where: {userid: filters.subcon_id}, // Subcon
}
]
}],
where: {
reference_date: filters.reference_date
},
order:[
["id","DESC"]
],
offset:((page-1)*limit),
limit : limit,
subQuery:false
}).then(function(foundObject){
willFulfillDeferred.resolve(foundObject);
});
The where clause is the one with the comment Client, SC and Subcon. However, what is the best approach if those where clause is optional? I am using that for search filter. So if filters.leads_id is null then the where: {leads_id: filters.leads_id}, // Client should not be included in the query. Same with the others. The only solution I can think of is repeat those code blocks for each scenario of not null parameters but that's to repetitive and not practical.
Any other approach or solutions?
If I understand correctly, I think as a first step, you should define your respective where clauses, conditionally upon wether or not each specific search criteria is set:
const clientWhere = filters.leads_id ? {leads_id: filters.leads_id} : {}
const scWhere = filters.sc_id ? {hiring_coordinator_id: {$in: filters.sc_id}} : {}
const subconWhere = filters.subcon_id ? {userid: filters.subcon_id} : {}
So at this point if a search option isn't set, there'll just be an empty object as the where clause.
Next, use those pre-defined where clause objects in your query:
Time_Sheet_Details.findAll({
include: [
{
model: timesheetNotesSubcon,
required: false,
attributes:["note","file_name", "id", "working_hrs", "timestamp", "has_screenshot", "notes_category"]
},
{
model: Timesheet,
attributes:["id","leads_id","userid"],
where: clientWhere, // Client
include:[
{
model: Lead_Info, attributes:["id","fname","lname","email","hiring_coordinator_id","status"],
where: scWhere, // SC
include:[{
model: adminInfoSchema,
required: false,
attributes:["admin_id","admin_fname", "admin_lname", "admin_email", "signature_contact_nos", "signature_company"],
}]
},
{
model:Personal_Info,attributes:["userid","fname","lname","email"],
where: subconWhere, // Subcon
}
]
}],
where: {
reference_date: filters.reference_date
},
order:[
["id","DESC"]
],
offset:((page-1)*limit),
limit : limit,
subQuery:false
}).then(function(foundObject){
willFulfillDeferred.resolve(foundObject);
});

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

Categories

Resources