Mongoose how to write a query with if condition?
aggregation-framework, mean-stack, mongodb, mongoose, node.js
Solution
You can use javascript to dynamically create json document based on your query parameters.
Your updated function will look something like
post.getSpecificDateRangeJobs = function(queryData, callback) {
var matchCriteria = queryData.matchCriteria;
var currentDate = new Date();
// match document
var match = {
"expireDate": {
"$gte": currentDate
}
};
if (matchCriteria !== "") {
match["$text"]: {
"$search": matchCriteria
}
};
// group document
var group = {
_id: null
};
// Logic to calculate hours difference between current date and publish date is less than 30 hours.
if (queryData.dateGroups.thirtyHourAgo) {
group["thirtyHourAgo"] = {
"$sum": {
"$cond": [{
"$lte": [{
"$divide": [{
"$subtract": [currentDate, "$publishDate"]
}, 1000 * 60 * 60]
}, 30]
},
1,
0
]
}
};
}
// Similarly add more grouping condition based on query params.
var postsCollection = post.getDataSource().connector.collection(
post.modelName
);
// Use aggregate builder to create aggregation pipeline.
postsCollection.aggregate()
.match(match)
.group(group)
.exec(function(err, groupByRecords) {
if (err) {
return callback("err");
}
return callback(null, groupByRecords);
});
};
Problem
Suppose I have the following query: ``` post.getSpecificDateRangeJobs = function(queryData, callback) { var matchCriteria = queryData.matchCriteria; var currentDate = new Date(); var match = { expireDate: { $gte: new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate()) } }; if (queryData.matchCriteria !== "") { match = { expireDate: { $gte: new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate()) }, $text: { $search: matchCriteria } }; } var pipeline = [ { $match: match }, { $group: { _id: null, thirtyHourAgo: { $sum: { $cond: [ { $gte: [ "$publishDate", new Date(queryData.dateGroups.thirtyHourAgo) ] }, 1, 0 ] } }, fourtyEightHourAgo: { $sum: { $cond: [ { $gte: [ "$publishDate", new Date(queryData.dateGroups.fourtyHourAgo) ] }, 1, 0 ] } }, thirtyDaysAgo: { $sum: { $cond: [ { $lte: [ "$publishDate", new Date(queryData.dateGroups.oneMonthAgo) ] }, 1, 0 ] } } } } ]; var postsCollection = post.getDataSource().connector.collection( post.modelName ); postsCollection.aggregate(pipeline, function(err, groupByRecords) { if (err) { return callback("err"); } return callback(null, groupByRecords); }); }; ``` What i want to do is: 1- check if `queryData.dateGroups.thirtyHourAgo` existed and has value, then only add the relevant match clause in query (count of posts only for past 30 hour). 2- check if `queryData.dateGroups.fourtyHourAgo` existed, then add relevant query section (count of posts for past 30 hour, and past 48 hour ago). 3 and the same for `queryData.dateGroups.oneMonthAgo` (count of posts for past 30 hour, 48 hour, and past one month). I need something like Mysql if condition to check if a variable existed and not empty then include a query clause. Is it possible to do that? My sample data is like: ``` /* 1 */ { "_id" : ObjectId("58d8bcf01caf4ebddb842855"), "vacancyNumber" : "123213", "position" : "dsfdasf", "number" : 3, "isPublished" : true, "publishDate" : ISODate("2017-03-11T00:00:00.000Z"), "expireDate" : ISODate("2017-05-10T00:00:00.000Z"), "keywords" : [ "dasfdsaf", "afdas", "fdasf", "dafd" ], "deleted" : false } /* 2 */ { "_id" : ObjectId("58e87ed516b51f33ded59eb3"), "vacancyNumber" : "213123", "position" : "Software Developer", "number" : 4, "isPublished" : true, "publishDate" : ISODate("2017-04-14T00:00:00.000Z"), "expireDate" : ISODate("2017-05-09T00:00:00.000Z"), "keywords" : [ "adfsadf", "dasfdsaf" ], "deleted" : false } /* 3 */ { "_id" : ObjectId("58eb5b01c21fbad780bc74b6"), "vacancyNumber" : "2432432", "position" : "Web Designer", "number" : 4, "isPublished" : true, "publishDate" : ISODate("2017-04-09T00:00:00.000Z"), "expireDate" : ISODate("2017-05-12T00:00:00.000Z"), "keywords" : [ "adsaf", "das", "fdafdas", "fdas" ], "deleted" : false } /* 4 */ { "_id" : ObjectId("590f04fbf97a5803636ec66b"), "vacancyNumber" : "4354", "position" : "Software Developer", "number" : 5, "isPublished" : true, "publishDate" : ISODate("2017-05-19T00:00:00.000Z"), "expireDate" : ISODate("2017-05-27T00:00:00.000Z"), "keywords" : [ "PHP", "MySql" ], "deleted" : false } ``` Suppose I have three link in my application interface: 1- 30 hour ago posts. 2- 48 hour ago posts. 3- last one month posts. Now if user click on first link i should control to group posts only for 30 hour ago, but if user click on second link, i should prepare my query to group posts for 30 hour and also for 48 hour, and if user click on third link i should prepare for all of them. I want something like: ``` var pipeline = [ { $match: match }, { $group: { _id: null, if (myVariable) { thirtyHourAgo: { ........ ........ } } if (mysecondVariable) { fortyEightHourAgo: { ........ ........ } } ```