Sequelize conditional inclusion of where clause nodejs - javascript

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

Related

Sequelize - MySQL error: SELECT list is not in GROUP BY clause

I have this function which returns the categories containing the product with the lowest price.
async getAllWithMinPrice(req, res, next) {
try {
const categories = await Category.findAll({
attributes: ["id", "name"],
group: ["products.id"],
include: [
{
model: Product,
attributes: [
"id",
"name",
"pluralName",
"description",
"image",
[Sequelize.fn("MIN", Sequelize.col("price")), "minPrice"],
],
include: [
{
model: Type,
attributes: [],
},
],
},
],
});
return res.json(categories);
} catch (e) {
return next(ApiError.badRequest(e.message ? e.message : e));
}
}
But I am getting an error: "Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'fotoluks.category.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by".
On my test server, I just disabled ONLY_FULL_GROUP_BY in MySQL, but I don't have permission to do so on the current server.
As far as I understand, to solve this problem, you need to use any_value, but I just can't figure out how to do it in Sequelize.
P.S. In a similar function, I had exactly the same error, then I solved it by simply adding attributes: [], but in this case I can't do it.
you need to include those attributes in group by:
where: { //condition },
attributes: [
"provider_id",
"product_id",
"quantity",
[Sequelize.fn("sum", Sequelize.col("product_price")),"total_amount"],
],
group: ["provider_id", "product_id", "quantity"],

Sequelize query with nested array object json

I have data stored in a Postgres 11 table, one of the columns has a json object as it follows:
id
data
client_id
1
JSON
BR_123
{
"shed": false,
"transactions": [
{
"id": 1,
"value": 5000,
"depositDate": "2021-09-20T10:29:05.000Z",
"expirationDate": "2022-03-29T10:29:05.000Z",
"requestDate": "2021-09-17T17:04:43.000Z"
}
],
"applies": false,
"importValue": null,
"depositValue": null
}
What I'm trying to do is select all of the entries that have a 'transactions.value' greater or equal than a given amount.
Sequelize:
const clients = await ComercialImports.findAll({
where: {
status: 'Running'
},
attributes: ['id', 'mode', 'importerId'],
include: [
{
model: ComercialImportsTransactions,
as: 'importTransaction',
attributes: ['id', 'data', 'clientId'],
required: true,
where: {
data: {
transactions: {
value: {
[Op.gte]: 5000
}
}
}
}
}
]
});
Unfortunately, for some reason this query won't work, as it always return 0 results. I can't seem to access any values stored on the transactions entry. All other entries are accessible (e.g. I can query for all data with 'shed' = true)
What am I doing wrong?

Sequelize receiving empty array while filtering with association at top level

Sequelize version: 6.6.2
Context
I have 3 models: User, Food, UserFoods. They have a Super Many-to-Many relationship between them using the documentation.
const User = sequelize.define('user', {
username: DataTypes.STRING,
});
const Food = sequelize.define('food', {
name: DataTypes.STRING
});
const UserFoods = sequelize.define('user_foods', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
status: DataTypes.INTEGER,
});
User.belongsToMany(Food, { through: UserFoods });
Food.belongsToMany(User, { through: UserFoods });
User.hasMany(UserFoods);
UserFoods.belongsTo(User);
Food.hasMany(UserFoods);
UserFoods.belongsTo(Food);
The status column in UserFoods will receive a number when adding a food to a user that will be used to create the user food lists (favorite, good, suck...).
This way I can query like this:
const foods = await UserFoods.findAll({
where: { userId: req.userId, status: 1 },
include: Food,
});
The Problem
Now I'm trying to query all Foods that are not in any of the user lists. Im doing the following:
const foods = await Food.findAll({
where: {
"$user_foods.userId$": { [Op.not]: req.userId },
},
include: {
model: UserFoods,
duplicating: false,
},
limit: 10,
});
// output foods: []
Why am I receiving an empty array?
If I change the Op.not to Op.eq it will return all the foods that belongs to that user, so why doesn't work the other way around?
Use Op.ne insead of Op.not
where: {
"$user_foods.userId$": { [Op.ne]: req.userId },
},
I found out a question about SQL Joins and it suggests using null on the key of the second table.
const foods = await Food.findAll({
where: {
[Op.or]: [
{ "$user_foods.userId$": { [Op.ne]: req.userId } },
{ "$user_foods.userId$": { [Op.is]: null } },
]
},
include: {
model: UserFoods,
duplicating: false,
},
limit: 10,
});
So for the Foods that have users associated, return only foods that are not associated with the current user.
OR
Return all Foods that does not have any associated user.
This is working but i'm not sure if is the best way to do it since I don't have much experience with Sequelize and SQL.

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