MongoDB aggregate multiple group by top fields and array fields - mongodb

My collection will look like this,
{
"_id" : ObjectId("591c5971240033283736860a"),
"status" : "Done",
"createdDate" : ISODate("2017-05-17T14:09:20.653Z")
"communications" : [
{
"communicationUUID" : "df07948e-4a14-468e-beb1-db55ff72b215",
"communicationType" : "CALL",
"recipientId" : 12345,
"createdDate" : ISODate("2017-05-18T14:09:20.653Z")
"callResponse" : {
"Status" : "completed",
"id" : "dsd45554545ds92a9bd2c12e0e6436d",
}
}
]}
{
"_id" : ObjectId("45sdsd59124003345121450a"),
"status" : "ToDo",
"createdDate" : ISODate("2017-05-17T14:09:20.653Z")
"communications" : [
{
"communicationUUID" : "45sds55-4a14-468e-beb1-db55ff72b215",
"communicationType" : "CALL",
"recipientId" : 1234,
"createdDate" : ISODate("2017-05-18T14:09:20.653Z")
"callResponse" : {
"Status" : "completed",
"id" : "84fe862f1924455dsds5556436d",
}
}
]}
Currently I am writing two aggregate query to achieve my requirement and my query will be below
db.collection.aggregate(
{ $project: {
dayMonthYear: { $dateToString: { format: "%d/%m/%Y", date: "$createdDate" } },
status: 1,
}},
{ $group: {
_id: "$dayMonthYear",
Pending: { $sum: { $cond : [{ $eq : ["$status", "ToDo"]}, 1, 0]} },
InProgress: { $sum: { $cond : [{ $eq : ["$status", "InProgress"]}, 1, 0]} },
Done: { $sum: { $cond : [{ $eq : ["$status", "Done"]}, 1, 0]} },
Total: { $sum: 1 }
}}
My output will be,
{"_id" : "17/05/2017", "Pending" : 1.0, "InProgress" : 0.0, "Done" : 1.0, "Total" : 2.0 }
Using above query I can able to get count but I need to find the count based on communication Status too so I am writing one more query to achieve,
db.collection.aggregate(
{"$unwind":"$communications"},
{ $project: {
dayMonthYear: { $dateToString: { format: "%d/%m/%Y", date: "$createdDate" } },
communications: 1
}},
{ "$group": {
_id: "$dayMonthYear",
"total_call": { $sum: { $cond : [{ $or : [ { $eq: [ "$communications.callResponse.Status", "failed"] },
{ $eq: [ "$communications.callResponse.Status", "busy"] },
{ $eq: [ "$communications.callResponse.Status", "completed"] },
{ $eq: [ "$communications.callResponse.Status", "no-answer"] }
]}, 1, 0 ] }},
"engaged": { $addToSet: { $cond : [{ $eq : ["$communications.callResponse.Status", "completed"]},
"$communications.recipientId", "null" ]} },
"not_engaged": { $addToSet: { $cond: [{ $or : [ { $eq: [ "$communications.callResponse.Status", "failed"] },
{ $eq: [ "$communications.callResponse.Status", "busy"] },
{ $eq: [ "$communications.callResponse.Status", "no-answer"] } ]},
"$communications.recipientId", "null" ] }}
}},
{ "$project": {
"_id": 1,
"total_call": 1,
"engaged": { "$setDifference": [ "$ngaged", ["null"] ] },
"not_engaged": { "$setDifference": [ "$not_engaged", ["null"] ] },
}},
{ "$project": {
"total_call": 1,
"engaged": { "$size": "$engaged" },
"not_engaged": { "$size": { "$setDifference": [ "$not_engaged", "$engaged" ] }},
}})
My output will be,
{"_id" : "18/05/2017", "total_call" : 2.0, "engaged" : 2, "not_engaged" : 0}
Using above query I can able to get count but I want to achieve it in single query
I am looking for output like
{"_id":"17/05/2017", "Pending" : 1.0, "InProgress" : 0.0, "Done" : 1.0, "total_call" : 0, "engaged" : 0, "not_engaged" : 0}
{"_id":"18/05/2017", "Pending" : 0.0, "InProgress" : 0.0, "Done" : 0.0, "total_call" : 2, "engaged" : 2, "not_engaged" : 0}
Can anyone suggest or provide me good way to get above result.

You can use $concatArrays to merge the status& createdDate documents followed by $group to count the occurrences.
db.collection.aggregate([
{
"$project": {
"statusandcreateddate": {
"$concatArrays": [
[
{
"status": "$status",
"createdDate": "$createdDate"
}
],
{
"$map": {
"input": "$communications",
"as": "l",
"in": {
"status": "$$l.callResponse.Status",
"createdDate": "$$l.createdDate"
}
}
}
]
}
}
},
{
"$unwind": "$statusandcreateddate"
},
{
"$group": {
"_id": {
"$dateToString": {
"format": "%d/%m/%Y",
"date": "$statusandcreateddate.createdDate"
}
},
"total_call": {
"$sum": {
"$cond": [
{
"$or": [
{
"$eq": [
"$statusandcreateddate.status",
"failed"
]
},
{
"$eq": [
"$statusandcreateddate.status",
"busy"
]
},
{
"$eq": [
"$statusandcreateddate.status",
"completed"
]
},
{
"$eq": [
"$statusandcreateddate.status",
"no-answer"
]
}
]
},
1,
0
]
}
},
"engaged": {
"$sum": {
"$cond": [
{
"$eq": [
"$statusandcreateddate.status",
"completed"
]
},
1,
0
]
}
},
"not_engaged": {
"$sum": {
"$cond": [
{
"$or": [
{
"$eq": [
"$statusandcreateddate.status",
"failed"
]
},
{
"$eq": [
"$statusandcreateddate.status",
"busy"
]
},
{
"$eq": [
"$statusandcreateddate.status",
"no-answer"
]
}
]
},
1,
0
]
}
},
"Pending": {
"$sum": {
"$cond": [
{
"$eq": [
"$statusandcreateddate.status",
"ToDo"
]
},
1,
0
]
}
},
"InProgress": {
"$sum": {
"$cond": [
{
"$eq": [
"$statusandcreateddate.status",
"InProgress"
]
},
1,
0
]
}
},
"Done": {
"$sum": {
"$cond": [
{
"$eq": [
"$statusandcreateddate.status",
"Done"
]
},
1,
0
]
}
}
}
}
])

Related

How to use aggregate in mongodb

I have data like this in mongodb
{
"_id" : 1,
"data" : "ARIN",
"status" : "CLOSED",
"createdDate" : Date("2020-02-16T17:32:28+07:00")
},
{
"_id" : 2,
"source" : "ARIN",
"status" : "NEW",
"createdDate" : Date("2020-02-16T17:32:28+07:00")
},
{
"_id" : 3,
"data" : "APNIC",
"status" : "ONPROGRESS",
"createdDate" : Date("2020-02-17T17:32:28+07:00")
},
{
"_id" : 4,
"data" : "RIPE",
"status" : "NEW",
"createdDate" : Date("2020-02-17T17:32:28+07:00")
}
I want to result like this
{
statusNew : 2,
statusOnProgress : 1,
statusClosed : 1
statusTicketClosedDate1602 : 1,
statusTicketNewdDate1602 : 1,
statusTicketOnProgressDate1602 : 0
}
I have try use group and cond in mongodb, but to no avail. How can I write this query?
You can use this query,
db.collection.aggregate([{
$group: {
_id: null,
statusNew: { $sum: { $cond: [{ "$eq": ["$status", "NEW"] }, 1, 0] } },
statusOnProgress: { $sum: { $cond: [{ "$eq": ["$status", "ONPROGRESS"] }, 1, 0] } },
statusClosed: { $sum: { $cond: [{ "$eq": ["$status", "CLOSED"] }, 1, 0] } },
statusTicketClosedDate1602: {
$sum: {
$cond: [{
$and: [{ "$eq": ["$status", "CLOSED"] },
{ "$gte": ["$createdDate", ISODate("2020-02-16T00:00:00Z")] },
{ "$lt": ["$createdDate", ISODate("2020-02-17T00:00:00Z")] }]
}, 1, 0]
}
},
statusTicketNewdDate1602: {
$sum: {
$cond: [{
$and: [{ "$eq": ["$status", "NEW"] },
{ "$gte": ["$createdDate", ISODate("2020-02-16T00:00:00Z")] },
{ "$lt": ["$createdDate", ISODate("2020-02-17T00:00:00Z")] }]
}, 1, 0]
}
},
statusTicketOnProgressDate1602: {
$sum: {
$cond: [{
$and: [{ "$eq": ["$status", "ONPROGRESS"] },
{ "$gte": ["$createdDate", ISODate("2020-02-16T00:00:00Z")] },
{ "$lt": ["$createdDate", ISODate("2020-02-17T00:00:00Z")] }]
}, 1, 0]
}
}
}
}])

How to add two collections with single aggregation

I am new to MongoDb and would appreciate some help with this query. I wrote the following aggregation pipeline. I wrote the query from collection1 I got the output ("Conventional Energy" : 0.0036) and I wrote the query collection2 I got the output (LastMonthConsumption" : 2.08) but how to add two collection with single aggregation with(LastMonthConsumption" : 2.08 * Conventional Energy" : 0.0036/Conventional Energy" : 0.0036) this is my required output
I have this data in mongodb:
COLLECTION 1:DATA
{
"slcId" : "51",
"clientId" : "1",
"dcuId" : "1",
"type" : "L",
"officeId" : "200-24",
"lampStatus" : "OFF",
"cummulativeKWH" : 133.7,
"powerFactor" : 1.0,
"createDate" : ISODate("2018-09-06T00:01:34.816Z")
},
{
"slcId" : "52",
"clientId" : "1",
"dcuId" : "1",
"type" : "L",
"officeId" : "200-24",
"lampStatus" : "OFF",
"cummulativeKWH" : 133.7,
"powerFactor" : 1.0,
"createDate" : ISODate("2018-09-07T21:01:34.816Z")
}
COLLECTION2:DATA
{
"_class" : "MongoStreetLightMonthlyVo",
"timeId" : ISODate("2018-08-04T16:40:08.817Z"),
"vendor" : "CIMCON",
"slcId" : "123450",
"mongoStreetLightChildVo" : {
"totalConsumptionMtd" : 2.08,
"prevConsumptionMtd" : 3.45,
"perChargeKWH" : 9.85,
}
},
{
"_class" : "MongoStreetLightMonthlyVo",
"timeId" : ISODate("2018-09-04T16:40:08.817Z"),
"vendor" : "CIMCON",
"slcId" : "123450",
"mongoStreetLightChildVo" : {
"totalConsumptionMtd" : 2.08,
"prevConsumptionMtd" : 3.45,
"perChargeKWH" : 9.85,
}
}
Collection1:
db.collection1.aggregate([
{ $match:{"type" : "L"}},
{
$count: "TOTAL_Lights"
},
{ "$project": {
"Conventional Energy": {
"$divide": [
{ "$multiply": [
{ "$multiply": [ "$TOTAL_Lights" ,0.12 ] },
]},
1000
]
}
}},
])
output: {"Conventional Energy" : 0.0036}
Collection2:
db.collection2.aggregate(
[
// Stage 1
{
$group: {
_id:{year:{$year:"$timeId"},month:{$month:"$timeId"} },
LastMonthConsumption : {$sum:"$mongoStreetLightChildVo.totalConsumptionMtd"},
}
},
{
$redact: {
$cond: { if: { $and:[
{$eq: [ "$_id.year", {$year:new Date()} ]},
{$eq: [-1, {$subtract:[ "$_id.month", {$month:new Date()} ]}]}
]},
then: "$$KEEP",
else: "$$PRUNE"
}
}
},
{$project:{
_id:0,
LastMonthConsumption :1
}
}
]
);
output:{
"LastMonthConsumption" : 2.08
}
Expected output:
LastMonthConsumption - Conventional Energy/Conventional Energy*100
You can try below aggregation
db.collection2.aggregate([
{ "$group": {
"_id": { "year": { "$year": "$timeId" }, "month": { "$month": "$timeId" }},
"LastMonthConsumption": { "$sum": "$mongoStreetLightChildVo.totalConsumptionMtd" }
}},
{ "$redact": {
"$cond": {
"if": {
"$and": [
{ "$eq": ["$_id.year", { "$year": new Date() }] },
{ "$eq": [-1, { "$subtract": ["$_id.month", { "$month": new Date() }] }]
}
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$lookup": {
"from": "collection1",
"pipeline": [
{ "$match": { "type": "L" } },
{ "$count": "TOTAL_Lights" },
{ "$project": {
"ConventionalEnergy": {
"$divide": [{ "$multiply": [{ "$multiply": ["$TOTAL_Lights", 0.12] }] }, 1000]
}
}}
],
"as": "ConventionalEnergy"
}},
{ "$project": {
"_id": 0,
"totalConsumption": {
"$multiply": [
{
"$divide": [
{
"$subtract": [
"$LastMonthConsumption",
{ "$arrayElemAt": ["$ConventionalEnergy.ConventionalEnergy", 0] }
]
},
{ "$arrayElemAt": ["$ConventionalEnergy.ConventionalEnergy", 0] }
]
},
100
]
}
}}
])

MongoDB group and compute results from multiple fields within same document

Can I have your help regarding MongoDB aggregation framework. I trying to build a Premier League Table from following collection of games:
{
"_id" : ObjectId("5b39fec4b5f8df161d259f36"),
"gameWeek" : 1,
"homeTeam" : "Arsenal",
"awayTeam" : "Leicester",
"homeGoals" : 2,
"awayGoals" : 1
}, {
"_id" : ObjectId("5b39ffc2b5f8df161d259f6d"),
"gameWeek" : 2,
"homeTeam" : "Arsenal",
"awayTeam" : "Sunderland",
"homeGoals" : 1,
"awayGoals" : 1
}, {
"_id" : ObjectId("5b39ffe8b5f8df161d259f7f"),
"gameWeek" : 2,
"homeTeam" : "Sunderland",
"awayTeam" : "Manchester United",
"homeGoals" : 1,
"awayGoals" : 1
}, {
"_id" : ObjectId("5b492cbea5aef964f0911cce"),
"gameWeek" : 1,
"homeTeam" : "Manchester United",
"awayTeam" : "Leicester",
"homeGoals" : 0,
"awayGoals" : 1
}
I wish to get following results:
{
"_id" : "Arsenal",
"team" : "Arsenal",
"gamesPlayed" : 2,
"goalsFor" : 3,
"goalsAgainst" : 2,
"goalsDifference" : 1,
"gamesWon" : 1,
"gamesDraw" : 1,
"gamesLost" : 0,
"points" : 4
}, {
"_id" : "Leicester",
"team" : "Leicester",
"gamesPlayed" : 2,
"goalsFor" : 2,
"goalsAgainst" : 2,
"goalsDifference" : 0,
"gamesWon" : 1,
"gamesDraw" : 0,
"gamesLost" : 1,
"points" : 3
}, {
"_id" : "Sunderland",
"team" : "Sunderland",
"gamesPlayed" : 2,
"goalsFor" : 2,
"goalsAgainst" : 2,
"goalsDifference" : 0,
"gamesWon" : 0,
"gamesDraw" : 2,
"gamesLost" : 0,
"points" : 2
}, {
"_id" : "Manchester United",
"team" : "Manchester United",
"gamesPlayed" : 2,
"goalsFor" : 1,
"goalsAgainst" : 2,
"goalsDifference" : -1,
"gamesWon" : 0,
"gamesDraw" : 1,
"gamesLost" : 1,
"points" : 1
}
where:
gamesPlayed - total number of the games played,
goalsFor - total goals made by team,
goalsAgainst - total let in goals,
goalsDifference - 'goalsFor' subtracting 'goalsAgainst'
points - gets calculated scoring 3 points for each won game and 1 point for every draw game.
So far I have following query for building team standing by homeTeam results:
db.football_matches.aggregate([
{
$group: {
_id: "$homeTeam",
gamesPlayed : { $sum: NumberInt(1) },
goalsFor: { $sum: "$homeGoals" },
goalsAgainst: { $sum: "$awayGoals" },
gamesWon: { $sum: { $cond: { if: { $gt: [ "$homeGoals", "$awayGoals" ]}, then: NumberInt(1), else: NumberInt(0) } }},
gamesDraw: { $sum: { $cond: { if: { $eq: [ "$homeGoals", "$awayGoals" ]}, then: NumberInt(1), else: NumberInt(0) } }},
gamesLost: { $sum: { $cond: { if: { $lt: [ "$homeGoals", "$awayGoals" ]}, then: NumberInt(1), else: NumberInt(0) } }}
}
}, {
$project: {
team: "$_id" ,
gamesPlayed: "$gamesPlayed",
goalsFor: "$goalsFor",
goalsAgainst: "$goalsAgainst",
goalsDifference: { $subtract: [ "$goalsFor", "$goalsAgainst"] },
gamesWon: "$gamesWon",
gamesDraw: "$gamesDraw",
gamesLost: "$gamesLost",
points: { $add: [ {$multiply: [ "$gamesWon", NumberInt(3)]}, {$multiply: [ "$gamesDraw", NumberInt(1)]} ]}
}
}, {
$sort: { points: -1, goalsDifference: -1 }
}
])
Theoretically I need to combine following grouping results with another similar group statement where similar action will be perform against awayTeam fields:
{
$group: {
_id: "$awayTeam",
gamesPlayed : { $sum: NumberInt(1) },
goalsFor: { $sum: "$awayGoals" },
goalsAgainst: { $sum: "$homeGoals" },
gamesWon: { $sum: { $cond: { if: { $gt: [ "$awayGoals", "$homeGoals" ]}, then: NumberInt(1), else: NumberInt(0) } }},
gamesDraw: { $sum: { $cond: { if: { $eq: [ "$awayGoals", "$homeGoals" ]}, then: NumberInt(1), else: NumberInt(0) } }},
gamesLost: { $sum: { $cond: { if: { $lt: [ "$awayGoals", "$homeGoals" ]}, then: NumberInt(1), else: NumberInt(0) } }}
}
}
How can I do that? Thank you very much. Please accept my apologies if similar question was asked before.
You can try below aggregation using $facet, $replaceRoot, $unwind, $concatArrays and finally with one more $group stage
db.collection.aggregate([
{ "$facet": {
"first": [
{ "$group": {
"_id": "$homeTeam",
"gamesPlayed": { "$sum": 1 },
"goalsFor": { "$sum": "$homeGoals" },
"goalsAgainst": { "$sum": "$awayGoals" },
"gamesWon": {
"$sum": { "$cond": { "if": { "$gt": [ "$homeGoals", "$awayGoals" ] }, "then": 1, "else": 0 } }
},
"gamesDraw": {
"$sum": { "$cond": { "if": { "$eq": [ "$homeGoals", "$awayGoals" ] }, "then": 1, "else": 0 } }
},
"gamesLost": {
"$sum": { "$cond": { "if": { "$lt": [ "$homeGoals", "$awayGoals" ] }, "then": 1, "else": 0 } }
}
}},
{ "$project": {
"team": "$_id",
"gamesPlayed": "$gamesPlayed",
"goalsFor": "$goalsFor",
"goalsAgainst": "$goalsAgainst",
"goalsDifference": { "$subtract": [ "$goalsFor", "$goalsAgainst" ] },
"gamesWon": "$gamesWon",
"gamesDraw": "$gamesDraw",
"gamesLost": "$gamesLost",
"points": { "$add": [{ "$multiply": [ "$gamesWon", 3 ] }, { "$multiply": [ "$gamesDraw", 1 ] }] }
}},
{ "$sort": { "points": -1, "goalsDifference": -1 } }
],
"second": [
{ "$group": {
"_id": "$awayTeam",
"gamesPlayed": { "$sum": 1 },
"goalsFor": { "$sum": "$awayGoals" },
"goalsAgainst": { "$sum": "$homeGoals" },
"gamesWon": {
"$sum": { "$cond": { "if": { "$gt": [ "$awayGoals", "$homeGoals" ] }, "then": 1, "else": 0 } }
},
"gamesDraw": {
"$sum": { "$cond": { "if": { "$eq": [ "$awayGoals", "$homeGoals" ] }, "then": 1, "else": 0 } }
},
"gamesLost": {
"$sum": { "$cond": { "if": { "$lt": [ "$awayGoals", "$homeGoals" ] }, "then": 1, "else": 0 } }
}
}},
{ "$project": {
"team": "$_id",
"gamesPlayed": "$gamesPlayed",
"goalsFor": "$goalsFor",
"goalsAgainst": "$goalsAgainst",
"goalsDifference": { "$subtract": [ "$goalsFor", "$goalsAgainst" ] },
"gamesWon": "$gamesWon",
"gamesDraw": "$gamesDraw",
"gamesLost": "$gamesLost",
"points": { "$add": [{ "$multiply": [ "$gamesWon",3 ] }, { "$multiply": [ "$gamesDraw",1 ] } ] }
}},
{ "$sort": { "points": -1, "goalsDifference": -1 } }
]
}},
{ "$project": {
"data": {
"$concatArrays": [ "$first", "$second" ]
}
}},
{ "$unwind": "$data" },
{ "$replaceRoot": { "newRoot": "$data" } },
{ "$group": {
"_id": "$_id",
"gamesPlayed": { "$sum": "$gamesPlayed" },
"goalsFor": { "$sum": "$goalsFor" },
"goalsAgainst": { "$sum": "$goalsAgainst" },
"gamesWon": { "$sum": "$gamesWon" },
"gamesDraw": { "$sum": "$gamesDraw" },
"gamesLost": { "$sum": "$gamesLost" }
}}
])

$push and $sum with the aggregation framework on sub-documents

I've a data as follows:
{
"_id" : ObjectId("55d4410544c96d6f6578f893"),
"executionProject" : "Project1",
"suiteList" : [
{
"suiteName": "Suite1",
"suiteStatus" : "PASS",
},
{
"suiteName": "Suite2",
"suiteStatus" : "FAIL",
},
{
"suiteName": "Suite3",
"suiteStatus" : "PASS",
}
],
"runEndTime" : ISODate("2015-08-19T08:40:47.049Z")
}
{
"_id" : ObjectId("55d4410544c96d6f6578f894"),
"executionProject" : "Project1",
"suiteList" : [
{
"suiteName": "Suite1",
"suiteStatus" : "PASS",
},
{
"suiteName": "Suite2",
"suiteStatus" : "FAIL",
},
{
"suiteName": "Suite3",
"suiteStatus" : "FAIL",
}
],
"runEndTime" : ISODate("2015-08-19T08:50:47.049Z")
}
And I was trying to get the result like this:
{
"executionProject": "Project1",
"data": [
{
"date": "2015-08-19 08:40:47",
"suitePass": 2,
"suiteFail": 1
},
{
"date": "2015-08-19 08:50:47",
"suitePass": 1,
"suiteFail": 2
}
]
}
Here I'm trying to group by executionProject and push the runEndTime and the pass and fail counts of suites to the result.
I tried this, but giving me wrong way of projection:
db.testruns.aggregate([
{
$project: {
executionProject: "$executionProject",
runEndTime: "$runEndTime",
suiteList: "$suiteList"
}
},
{
$unwind: "$suiteList"
},
{
$group: {
_id: "$executionProject",
runEndTime: {
$addToSet: "$runEndTime"
},
suite_pass: {
$sum: {
$cond: {
"if": {
$eq: ["$suiteList.suiteStatus", "PASS"]
},
"then": 1,
"else": 0
}
}
}
}
},
{
$group: {
_id: "$_id",
runEndTime: { $push: {runTime: "$runEndTime", suite_pass: "$suite_pass"} }
}
},
{
$project: {
executionProject: "$_id",
runEndTime: "$runEndTime",
_id: 0
}
}
]);
First you need to group by the document to get the suite totals, then you add to the array as you group on the project. Also don't forget to "sort" if you want things in order:
[
{ "$unwind": "$suiteList" },
{ "$group": {
"_id": "$_id",
"executionProject": { "$first": "$executionProject" },
"suite-pass": {
"$sum": {
"$cond": [
{ "$eq": [ "$suiteList.suiteStatus", "PASS" ] },
1,
0
]
}
},
"suite-fail": {
"$sum": {
"$cond": [
{ "$eq": [ "$suiteList.suiteStatus", "FAIL" ] },
1,
0
]
}
},
"date": { "$first": "$runEndTime" }
}},
{ "$sort": { "executionProject": 1, "date": 1 } },
{ "$group": {
"_id": "$executionProject",
"data": {
"$push": {
"suite-pass": "$suite-pass",
"suite-fail": "$suite-fail",
"date": "$date"
}
}
}}
]
Produces:
{
"_id" : "Project1",
"data" : [
{
"suite-pass" : 2,
"suite-fail" : 1,
"date" : ISODate("2015-08-19T08:40:47.049Z")
},
{
"suite-pass" : 1,
"suite-fail" : 2,
"date" : ISODate("2015-08-19T08:50:47.049Z")
}
]
}

Aggregate query in MongoDB

I'm trying to create some daily stats from a MongoDB table. The document contains messages that have a create-date, state (Warn, Error, Complete). I'd like to product a query that results in one record per - Date,Count of Warn, Count of Error, Count of Complete. I'm a newbie with Mongo and just learning the query language. I've tried aggregation with mixed results:
db.TransactionLogs.aggregate(
{ $group : {
_id : {
category: {$substr:["$startDate",0,10]},
term: "$Status",
},
total: { $sum : 2 }
}
})
results in multiple records per date by status:
"result" : [
{
"_id" : {
"category" : "2015-02-10",
"term" : "Completed",
},
"total" : 532
},
{
"_id" : {
"category" : "2015-02-10",
"term" : "Error",
},
"total" : 616
},
Message:
{ "_id" : "2ceda481-3dd3-480d-800d-95288edce6f2", "MID" : "02de5194-7a1d-4854-922c-934902840136", "Status" : "Completed", "firstName" : "Willy", "lastName" : "Wire", "allocation" : "100", "initEvent" : "Marriage", "system" : "Oracle", "startDate" : "2015-02-06T19:03:34.237Z", "stopDate" : "2015-02-06T19:23:34.237Z", "plan" : "445-A" }
I'm sure that its a lack of understanding of aggregation on my part. Any help or direction is greatly appreciated!
I figured it out. I needed to look at how to "pivot" in Mongo. This works:
db.TransactionLogs.aggregate([ { $project: { startdate: {$substr:["$startDate",0,10]},
cnt_e1: { $cond: [ { $eq: [ "$Status", "Error" ] }, "$count", 1 ] },
cnt_e2: { $cond: [ { $eq: [ "$Status", "Warning" ] }, "$count", 1 ] },
cnt_e3: { $cond: [ { $eq: [ "$Status", "Completed" ] }, "$count", 1 ] },
} },
{ $group: { _id: "$startdate", cnt_e1: { $sum: "$cnt_e1" }, cnt_e2: { $sum: "$cnt_e2" }, cnt_e3: { $sum: "$cnt_e3" } } },
{ $sort: { _id: 1 } },
Here's the code...
db.TransactionLogs.aggregate([ { $project: { startdate: {$substr:["$startDate",0,10]},
cnt_e1: { $cond: [ { $eq: [ "$Status", "Error" ] }, "$count", 1 ] },
cnt_e2: { $cond: [ { $eq: [ "$Status", "Warning" ] }, "$count", 1 ] },
cnt_e3: { $cond: [ { $eq: [ "$Status", "Completed" ] }, "$count", 1 ] },
} },
{ $group: { _id: "$startdate", cnt_e1: { $sum: "$cnt_e1" }, cnt_e2: { $sum: "$cnt_e2" }, cnt_e3: { $sum: "$cnt_e3" } } },
{ $sort: { _id: 1 } },