Reputation: 15
I am trying to filter an array of publications in a project with angular node and mongo, but when doing the query in mongo I can't make it work.
Any way so that if the params.category
parameter arrives null that parameter is not taken into account and the query works with the other parameters normally?
I wanted to add two if
before the query to make it work, but since I'm going to add another 3 filters (in addition to params.category
) I would have to add a lot of if
and it wouldn't look very good.
Hope someone can help me. ty
function getPublicationMap(req, res){
var params = req.body;
Publication.find({ $and: [{latitude: {$gt: params.south}}, {latitude: {$lt: params.north}}, {longitude: {$gt: params.west}},
{longitude: {$lt: params.east}}, {category: {$eq: params.category}} ]}, (err, publications) =>{
if(err) return res.status(500).send({message: 'Error'});
if(!publications) return res.status(404).send({message: 'No publications'});
return res.status(200).send({publications});
});
}
Upvotes: 0
Views: 3362
Reputation: 1
It is quite simple
if (role.length > 0) { console.log(role);
filterparams.push({ role: role });
}
if (min_salary > 0) {
console.log(typeof min_salary);
filterparams.push({ min_salary: { $gte: min_salary } });
}
if (max_salary > 0) {
console.log(typeof max_salary);
filterparams.push({ max_salary: { $lte: max_salary } });
}
if (job_type.length > 0) {
filterparams.push({ job_type: job_type });
}
if (work_policy.length > 0) {
console.log(work_policy);
filterparams.push({ work_policy: work_policy });
}
if (search.length > 0) {
console.log(`in search if condition`);
filterparams.push({
$text: {
$search: search
}
});
}
if (language.length > 0) {
if (language.length > 1) {
for (let i = 0; i < language.length; i++) langaugeparams.push({ 'job_desc.lang_code': language[i] });
filterparams.push({ $or: langaugeparams });
} else {
filterparams.push({ 'job_desc.lang_code': language[0] });
}
}
var result = await LiveJobsDBModel.find({ $and: filterparams })
what I have done , is that I have made an Object , and checked each parameter manually. If it's value is present then only I am adding this into the filterparams array, well this worked for me .
the filterparams array would look something like this.
filterparams = :[{‘role’:role},{min_salary:{$gte:min_salary)}},{max_salary:{$lte:max_salary}},{‘job_type’:job_type},{‘work_policy’:work_policy}]
Upvotes: 0
Reputation: 1049
If you don't want to put bunch of IFs for some reason then "query factory" function can be created:
function maybeCreateMongoQuery(prop,queryProp,value){
return value === null ? null : {[prop]: {[queryProp]: value}};
}
And then at middleware itself:
// ....
Publication.find({ $and: [
maybeCreateMongoQuery('latitude', '$gt', params.south),
maybeCreateMongoQuery('latitude', '$lt', params.north),
// ...
].filter(q => q !== null)
}, (err, publications) => {
// ....
});
Also, .filter(q => q !== null)
part can be extracted into separate function as well in case if you need to reuse solution multiple times.
But, keep in mind that by using such approach you're avoiding repetitive IFs on one hand, but increasing complexity on other hand. So, there are always tradeoffs.
Upvotes: 4
Reputation: 14317
The solution using aggregation:
db.collection.aggregate( [
{
$addFields: { isParamCategoryNull: { $eq: [ params.category, null ] } }
},
{
$addFields: {
matches: {
$cond: {
if: { $eq: [ "$isParamCategoryNull", true ] },
then: { $and: [ { $gt: [ "$latitude", param.south ] }, { $lt: [ "$latitude", param.north ] },
{ $gt: [ "$longitude", param.west ] }, { $lt: [ "$longitude", param.east ] }
]
},
else: { $and: [ { $gt: [ "$latitude", param.south ] }, { $lt: [ "$latitude", param.north ] },
{ $gt: [ "$longitude", param.west ] }, { $lt: [ "$longitude", param.east ] },
{ $eq: [ "$category", param.category ] }
]
}
}
} }
},
{
$match: { matches: true }
},
{
$project: { matches: 0, isParamCategoryNull: 0 }
}
] )
With these two input documents,
{ "_id" : 1, "latitude" : 12, "longitude" : 15, "category" : "xyz" },
{ "_id" : 2, "latitude" : 12, "longitude" : 18, "category" : "abc" }
when params = { south: 11, north: 15, west: 10, east: 20, category: null }
, both documents will be selected. If the params.category = "xyz"
, then only the document with _id: 1
will be selected.
Upvotes: 0