mongoose - group collection data by multiple fields mongodb -


collection structure

order = new schema     index:          { type: number, unique: true }     number:         date     status:         { type: string, enum: ['success', 'failure'] }     created_at:     { type: date, default: date.now }     updated_at:     { type: date, default: date.now } 

i need query returns me array of objects having data success count , failure count grouped date. ex-

orders = {               28-10-2016:{                success_count: 10,                 failure_count: 10               },               29-10-2016: {                success_count: 10,                 failure_count: 10               }           } 

with aggregation framework, result different "desired" output instead of having hash keys, array of objects _id key having value represents group field. instance, instead of

{     "28-10-2016":{         "success_count": 10,          "failure_count": 10     },     "29-10-2016": {         "success_count": 10,          "failure_count": 10     } } 

you'd have better structure like

[     {         "_id": "28-10-2016",         "success_count": 10,          "failure_count": 10     },         "_id": "29-10-2016",         "success_count": 10,          "failure_count": 10     } ] 

accomplishing above result require using $cond operator in $sum accumulator operator. $cond operator evaluate logical condition based on first argument (if) , returns second argument evaluation true (then) or third argument false (else). converts true/false logic 1 , 0 numerical values feed $sum respectively:

"success_count": {     "$sum": {         "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]     } } 

as resulting pipeline, 1 needs run aggregation operation uses $datetostring operator in _id key expression $group pipeline:

orders.aggregate([     {         "$group": {             "_id": {                 "$datetostring": {                      "format": "%y-%m-%d",                      "date": "$created_at"                  }             },             "success_count": {                 "$sum": {                     "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]                 }             },             "failure_count": {                 "$sum": {                     "$cond": [ { "$eq": [ "$status", "failure" ] }, 1, 0 ]                 }             }         }     } ], function (err, orders){     if (err) throw err;     console.log(orders); }) 

however, there more flexible , better performant approach executes faster above, efficient data structure aggregation result follows schema example:

orders = [     {         "_id": "28-10-2016",         "counts": [             { "status": "success", "count": 10 },             { "status": "failure", "count": 10 }         ]     },     {         "_id": "29-10-2016",         "counts": [             { "status": "success", "count": 10 },             { "status": "failure", "count": 10 }         ]     } ] 

then consider running alternative pipeline follows

orders.aggregate([     {          "$group": {             "_id": {                  "date":  {                     "$datetostring": {                          "format": "%y-%m-%d",                          "date": "$created_at"                      }                 },                 "status": { "$tolower": "$status" }             },             "count": { "$sum": 1 }         }     },     {          "$group": {             "_id": "$_id.date",             "counts": {                 "$push": {                     "status": "$_id.status",                     "count": "$count"                 }             }         }     } ], function (err, orders){     if (err) throw err;     console.log(orders); }) 

Comments

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -