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: {
........
........
}
}
We can specify as many conditions in the query field. But in cases, where we need to filter according to only one field but more than on values. For example, if we want every document where the value of the name field is more than one value, then what? For such cases, mongoose provides the $in operator.
The lean option tells Mongoose to skip hydrating the result documents. This makes queries faster and less memory intensive, but the result documents are plain old JavaScript objects (POJOs), not Mongoose documents.
The __v field is called the version key. It describes the internal revision of a document. This __v field is used to track the revisions of a document. By default, its value is zero ( __v:0 ).
In mongoose, exec method will execute the query and return a Promise.
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);
});
};
As I understood, I can suggest you following general query. Modify this according to your need.
db.getCollection('vacancy')
.aggregate([{$match: { $and: [
{publishDate:{ $gte: new Date(2017, 4, 13) }} ,
{publishDate:{ $lte: new Date(2017, 4, 14) }}
]} }])
Summary:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With