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

About Author

Author Image
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.

Request for Proposal

Name is required

Comment is required

Sending message..