Mongodb aggregate function with multiple if else condition
Posted By : Md Imroz Alam | 07-Aug-2016
For example: -
we take a collection name as "applicationUsage" which has field(userId,applicationName,duration,startTime,endTime).
we are saving application uses of individual user into applicationUsage collection.
case 1:
Let John used the application A, start From "12th May 2016 ko 11:50 pm" and end at "13th May 2016 12:15 am"
case 2:
Let John used the application B, start From "13th May 2016 3:00 pm" and end at "13th May 2016 5:00 pm"
case 3:
Let John used the application C, start From "13th May 2016 11:00 pm" and end at "14th May 2016 1:00 am"
-------------inserted record in db------------
date will be save as ISO date, only for understanding we are showing date as IST date
userId startTime endTime duration ApplicatonName
John 12th May 2016 11:50pm 13th May 2016 12:15 am 25 minute application A (case 1)
John 13th May 2016 3:00 pm 13th May 2016 5:00 pm 2 hours application B (case 2)
John 13th May 2016 11:00 pm 14th May 2016 1:00 am 2 hours application C (case 3)
Now, John wants to know which applicaton i have been used between "13th May 2016 12:00 am" to "13th May 2016 11:59pm".
-----------Desired output like---------------
userId duration ApplicatonName
John 15 minute(not to be 25 minute) application A(case 1)
John 2 hours application B(case 2)
John 59 minute(not be 2 hours) application C(case 3)
Step 1:
var filterDate={from:"2016-05-12T18:30:00.000Z",to:"2016-05-13T18:29:00.000Z"} // converted to ISO date
now , we are writing normal query.
var query=[{ userId: "John"}, { "startTime": { "$gte": new Date(filterDate.from)}},{ "endTime": {"$lte": new Date(filterDate.to) }}];
Now aggregate--> group by Application name, sum of application's duration,
db.applicationusage.aggregate([{ '$match': { $and: query }}, {$group: {"_id": {"application": "$application"},"count": { "$sum": "$duration" } } }, {$project: { _id: 0,application: '$_id.application',duration: "$count"}}],function(err,applicationResult){});
output:-
userId duration Application
John 2 hours application B (case 2)
only second record will be come.
then first of all , we have to get all those record which is lie between "13th May 2016 12:00 am" to "13th May 2016 11:59 pm"
Step 2:
now query ,
var left=[{ "startTime": { "$lt": new Date(filterDate.from) } },{ "endTime": { "$gt": new Date(filterDate.from), "$lte": new Date(filterDate.to) } }] // left Intersection record( case 1) var middle=[{ "startTime": { "$gte": new Date(filterDate.from)}},{ "endTime": {"$lte": new Date(filterDate.to) }}] //( case 2) var right=[{ "startTime": { "$gte": new Date(filterDate.from),"$lt": new Date(filterDate.to) } },{ "endTime": { "$gt": new Date(filterDate.to) }}] //Right intersection record (case 3) var query=[{ userId: "John"}, { $or:[{$and:left},{},{$and:middle},{$and:right}] }];
output:-
userId duration Applicaton
John 25 minute **(to be 15 minute) application A (case 1)
John 2 hours application B (case 2)
John 2 hours **(to be 1 hour) application C (case 3)
all record get but did not get desired result, duration is coming wrong.
Step 3:
Now aggregate, group by Application name, sum of duration with required condition for caluclating right duration,
$cond aggregate variable // for reference https://docs.mongodb.com/manual/reference/operator/aggregation/cond/
$subtract // for reference read https://docs.mongodb.com/manual/reference/operator/aggregation/subtract
$divide // for reference read https://docs.mongodb.com/v3.0/reference/operator/aggregation/divide
var sumCondition={ "$cond": { "if": { // (case 1 --> same as left varaible query ) "$and": [{ "$gt": ["$endTime", new Date(filterDate.from)] }, { "$lte": ["$endTime", new Date(filterDate.to)] }, { "$lt": ["$startTime", new Date(filterDate.from)] }] }, "then": { "$divide": [{ "$subtract": ["$endTime", new Date(filterDate.from)] }, 1000] // ( case 1 --> duration calculation) }, "else": { "$cond": { "if": { // (case 3 --> same as right variable query) "$and": [{ "$gte": ["$startTime", new Date(filterDate.from)] }, { "$lt": ["$startTime", new Date(filterDate.to)] }, { "$gt": ["$endTime", new Date(filterDate.to)] }] }, "then": { "$divide": [{ "$subtract": [new Date(filterDate.to), "$startTime"] }, 1000] //( case 3 --> duration calculation) }, "else": "$duration" ( case 2 --> whatever save in duration field) } } } };
Now Final aggregate with multiple condition,
db.applicationusage.aggregate([{ '$match': { $and: query }},
{$group: { "_id": {"systemProcess": "$systemProcess"},"count": { "$sum": someCondition }}},
{ $project: { _id: 0,duration: "$count",systemProcess: "$_id.systemProcess" } }],function(err,ApplicationResult){});
Note:- In this step, step 2 query used
final output:-
userId duration Applicaton
John 15 minute application A (case 1)
John 2 hours application B (case 2)
John 59 minute application C (case 3)
I hope this will be helpful.
Thank You
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Md Imroz Alam
Md. Imroz Alam is a bright Web App Developer, he has good knowledge of Java, J2SE, Jsp, Servlet, jdbc. His hobbies are watching movie, playing carom.