Need to find the difference between two values of attendance,group by ward_id, based on patient id for two dates. The result has dynamic values based on the array. The difference is between two dates. Key would be ward_id, the difference will be between counts of patient's visit to the ward.
Example sample data
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-03T21:31:29.902Z"),
"ward_id" : 2561
},
"count" : 4112,
"values" : [
{
"count" : 9,
"patient" : ObjectId("54766f973f35473ffc644618")
},
{
"count" : 19,
"patient" : ObjectId("546680e2d660e2dc5ebfea39")
},
{
"count" : 47,
"patient" : ObjectId("546680e3d660e2dc5ebfea72")
},
{
"count" : 1,
"patient" : ObjectId("546a137bdab5f21e612ea7ef")
},
{
"count" : 93,
"patient" : ObjectId("546680e3d660e2dc5ebfea89")
}
]
}
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-03T21:31:29.902Z"),
"ward_id" : 3720
},
"count" : 1,
"values" : [
{
"count" : 1,
"patient" : ObjectId("546a136ddab5f21e612ea6a6")
}
]
}
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-04T21:31:29.902Z"),
"ward_id" : 2561
},
"count" : 4112,
"values" : [
{
"count" : 10,
"patient" : ObjectId("54766f973f35473ffc644618")
},
{
"count" : 10,
"patient" : ObjectId("546680e2d660e2dc5ebfea39")
},
{
"count" : 6,
"patient" : ObjectId("5474e9e46606f32570fa48ff")
},
{
"count" : 1,
"patient" : ObjectId("5474e9e36606f32570fa48f2")
},
{
"count" : 1,
"patient" : ObjectId("546680e3d660e2dc5ebfea77")
},
{
"count" : 543,
"patient" : ObjectId("546680e2d660e2dc5ebfea43")
},
{
"count" : 1,
"patient" : ObjectId("5485fdc8d27a9122956b1c66")
}
]
}
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-04T21:31:29.902Z"),
"ward_id" : 3720
},
"count" : 1,
"values" : [
{
"count" : 7,
"patient" : ObjectId("546a136ddab5f21e612ea6a6")
}
]
}
Output
{
"ward_id":2561,
"result" : [{"person": ObjectId("54766f973f35473ffc644618"),
"count_1": 9,
"count_1": 10,
"difference":1 },{"person": ObjectId("546680e2d660e2dc5ebfea39"),
"count_1": 19,
"count_1": 10,
"difference":-9 } ....]
},
{
"ward_id":3720,
"result" : [{"person": ObjectId("546a136ddab5f21e612ea6a6"),
"count_1": 9,
"count_1": 10,
"difference":1 },{"person": ObjectId("546680e2d660e2dc5ebfea39"),
"count_1": 1,
"count_1": 7,
"difference":-6 }]
}
you can use the aggregation framework's $subtract operator outlined here: http://docs.mongodb.org/manual/reference/operator/aggregation-arithmetic/
db.wards.aggregate([
{
$match: {id: {$elemMatch: {ward_id: my_ward_id, ts: my_desired_ts}}},
},
{
$limit: 2
},
{
$project: {values: 1}
},
{
$unwind: '$values'
},
{
$match: {patient: my_patient_id}
},
{
$group: {
_id: null,
'count1': {$first: '$values.count'},
'count2': {$last: '$values.count'}
}
},
{
$subtract: ['$count1', '$count2']
}
])
i haven't tested this but it would probably look like something above
Related
This is an example of the collection I am working with
> db.grades.find().limit(5).forEach(printjson)
{
"_id" : ObjectId("50b59cd75bed76f46522c353"),
"student_id" : 0,
"class_id" : 30,
"scores" : [
{
"type" : "exam",
"score" : 14.34345947841966
},
{
"type" : "quiz",
"score" : 47.65945482174327
},
{
"type" : "homework",
"score" : 83.42772189120254
},
{
"type" : "homework",
"score" : 49.86812935368258
},
{
"type" : "homework",
"score" : 39.85525554437086
}
]
}
{
"_id" : ObjectId("50b59cd75bed76f46522c356"),
"student_id" : 0,
"class_id" : 27,
"scores" : [
{
"type" : "exam",
"score" : 60.19473636151568
},
{
"type" : "quiz",
"score" : 64.15966210014162
},
{
"type" : "homework",
"score" : 82.80835343023551
}
]
}
{
"_id" : ObjectId("50b59cd75bed76f46522c350"),
"student_id" : 0,
"class_id" : 5,
"scores" : [
{
"type" : "exam",
"score" : 88.22950674232497
},
{
"type" : "quiz",
"score" : 79.28962650427184
},
{
"type" : "homework",
"score" : 18.66254946562674
},
{
"type" : "homework",
"score" : 40.28154176513361
},
{
"type" : "homework",
"score" : 1.23735944117882
},
{
"type" : "homework",
"score" : 88.96101200683958
}
]
}
{
"_id" : ObjectId("50b59cd75bed76f46522c357"),
"student_id" : 0,
"class_id" : 11,
"scores" : [
{
"type" : "exam",
"score" : 58.83297411100884
},
{
"type" : "quiz",
"score" : 49.66835710930263
},
{
"type" : "homework",
"score" : 18.05861540807023
},
{
"type" : "homework",
"score" : 80.04086698967356
}
]
}
{
"_id" : ObjectId("50b59cd75bed76f46522c358"),
"student_id" : 0,
"class_id" : 10,
"scores" : [
{
"type" : "exam",
"score" : 30.93065784731665
},
{
"type" : "quiz",
"score" : 55.98003281528393
},
{
"type" : "homework",
"score" : 55.6752702814148
},
{
"type" : "homework",
"score" : 63.15391302252755
}
]
}
What I'm trying to achieve, is to get the highest score of the exam, where the student id is 5. I've been stuck on this for quite a while, and the furthest I've managed to come is to retrieve all of the student's exam scores, however I haven't managed to make it so only the highest scoring one displays. This is another aspect I'm stuck on.
This is the code for this output:
{
"student_id" : 5,
"class_id" : 18,
"scores" : [
{
"type" : "exam",
"score" : 73.04238861317688
}
]
}
{
"student_id" : 5,
"class_id" : 8,
"scores" : [
{
"type" : "exam",
"score" : 22.38732080941065
}
]
}
{
"student_id" : 5,
"class_id" : 0,
"scores" : [
{
"type" : "exam",
"score" : 43.64758440439862
}
]
}
{
"student_id" : 5,
"class_id" : 16,
"scores" : [
{
"type" : "exam",
"score" : 33.39752665396672
}
]
}
{
"student_id" : 5,
"class_id" : 30,
"scores" : [
{
"type" : "exam",
"score" : 73.48459944869943
}
]
}
{
"student_id" : 5,
"class_id" : 19,
"scores" : [
{
"type" : "exam",
"score" : 15.36563152024366
}
]
}
{
"student_id" : 5,
"class_id" : 23,
"scores" : [
{
"type" : "exam",
"score" : 21.58296008740177
}
]
}
The code that gets me this is as follows:
var pipeline = [
{ $match: {student_id: 5} },
{ $unwind: "$scores" },
{ $group: {
_id: "$_id",
"student_id": { "$first": "$student_id" },
"class_id": { "$first": "$class_id" },
scores: { $push: "$scores" } } },
{ $project: { _id: 0,
student_id: 1,
class_id: 1,
scores: { $slice: [ "$scores", 1] } } } ];
var results = db.grades.aggregate ( pipeline );
results.forEach(printjson)
(Sorry for the poor structuring, I did my best but I'm not used too it on stackoverflow)
I've been coding with MongoDB for about 2 days now, and I'm knowledgeable in it. Even less so with aggregates, but looking at posts and other code this seemed like the way to do it. From my point of view, because I'm already slicing through it, and attempting to sort the score will only result in getting the highest score out of exams, quiz and homeworks, so it's not a guarantee to give me the exam. Unless there's a different way to sort through these individually
Ideally, I'd want the end result to return only one document, where the exam score is the highest:
{
"student_id" : 5,
"class_id" : 30,
"scores" : [
{
"type" : "exam",
"score" : 73.48459944869943
}
]
}
$match student_id condition
$unwind deconstruct scores array
$match type: exam condition
$sort documents by score in descending order
$group by student_id and get first root document
$replaceRoot to replace doc to root
var pipeline = [
{ $match: { student_id: 5 } },
{ $unwind: "$scores" },
{ $match: { "scores.type": "exam" } },
{ $sort: { "scores.score": -1 } },
{
$group: {
_id: "$student_id",
doc: { $first: "$$ROOT" }
}
},
{ $replaceRoot: { newRoot: "$doc" } }
]
Playground
I am watching a tutorial I can understand how this aggregate works, What is the use of pings, $$ROOT in it.
client = pymongo.MongoClient(MY_URL)
pings = client['mflix']['watching_pings']
cursor = pings.aggregate([
{
"$sample": { "size": 50000 }
},
{
"$addFields": {
"dayOfWeek": { "$dayOfWeek": "$ts" },
"hourOfDay": { "$hour": "$ts" }
}
},
{
"$group": { "_id": "$dayOfWeek", "pings": { "$push": "$$ROOT" } }
},
{
"$sort": { "_id": 1 }
}
]);
Let's assume that our collection looks like below:
{
"_id" : ObjectId("b9"),
"key" : 1,
"value" : 20,
"history" : ISODate("2020-05-16T00:00:00Z")
},
{
"_id" : ObjectId("ba"),
"key" : 1,
"value" : 10,
"history" : ISODate("2020-05-13T00:00:00Z")
},
{
"_id" : ObjectId("bb"),
"key" : 3,
"value" : 50,
"history" : ISODate("2020-05-12T00:00:00Z")
},
{
"_id" : ObjectId("bc"),
"key" : 2,
"value" : 0,
"history" : ISODate("2020-05-13T00:00:00Z")
},
{
"_id" : ObjectId("bd"),
"key" : 2,
"value" : 10,
"history" : ISODate("2020-05-16T00:00:00Z")
}
Now based on the history field you want to group and insert the whole documents in to an array field 'items'. Here $$ROOT variable will be helpful.
So, the aggregation query to achieve the above will be:
db.collection.aggregate([{
$group: {
_id: '$history',
items: {$push: '$$ROOT'}
}
}])
It will result in following output:
{
"_id" : ISODate("2020-05-12T00:00:00Z"),
"items" : [
{
"_id" : ObjectId("bb"),
"key" : 3,
"value" : 50,
"history" : ISODate("2020-05-12T00:00:00Z")
}
]
},
{
"_id" : ISODate("2020-05-13T00:00:00Z"),
"items" : [
{
"_id" : ObjectId("ba"),
"key" : 1,
"value" : 10,
"history" : ISODate("2020-05-13T00:00:00Z")
},
{
"_id" : ObjectId("bc"),
"key" : 2,
"value" : 0,
"history" : ISODate("2020-05-13T00:00:00Z")
}
]
},
{
"_id" : ISODate("2020-05-16T00:00:00Z"),
"items" : [
{
"_id" : ObjectId("b9"),
"key" : 1,
"value" : 20,
"history" : ISODate("2020-05-16T00:00:00Z")
},
{
"_id" : ObjectId("bd"),
"key" : 2,
"value" : 10,
"history" : ISODate("2020-05-16T00:00:00Z")
}
]
}
I hope it helps.
I wanted to group by cart.name and find the sum of cart.qty in mongodb. Below is sample document
{
"_id" : ObjectId("581323379ae5e607645cb485"),
"cust" : {
"name" : "Customer 1",
"dob" : "09/04/1989",
"mob" : 999999999,
"loc" : "Karimangalam",
"aadhar" : {
}
},
"cart" : [
{
"name" : "Casual Shirt",
"qty" : 1,
"mrp" : 585,
"discperc" : 10,
"fit" : null,
"size" : "L"
},
{
"name" : "Casual Shirt",
"qty" : 1,
"mrp" : 500,
"discperc" : 0,
"fit" : null,
"size" : "L"
},
{
"name" : "Cotton Pant",
"qty" : 1,
"mrp" : 850,
"discperc" : 0,
"fit" : null,
"size" : "34"
},
{
"name" : "Cotton Pant",
"qty" : 1,
"mrp" : 1051,
"discperc" : 10,
"fit" : null,
"size" : "34"
}
],
"summary" : {
"bill" : 2822.4,
"qty" : 4,
"mrp" : 2986,
"received" : "2800",
"balance" : -22.40000000000009
},
"createdAt" : ISODate("2016-10-28T10:06:47.367Z"),
"updatedAt" : ISODate("2016-10-28T10:06:47.367Z")
}
There are many document like this. I want the output as below distinct product name (cart.name) and its total qty
{Casual Shirt , 30},
{Cotton Pant , 10},
{T-Shirt , 15},
{Lower , 12}
Here is my query trying to group by cart.name and sum qty
db.order.aggregate( [
{ $unwind: "$cart" },
{ $group: {
_id: "$cart.name",
totalQTY: { $sum:"$cart.qty"},
count: { $sum: 1 }
}
}
] )
but it displays wrong totalQty values for each product name. I checked manually.
Please give me the correct query.
> db.collection.aggregate([
... { $unwind: "$cart" },
... { $group: { "_id": "$cart.name", totalQTY: { $sum: "$cart.qty" }, count: { $sum: 1 } } }
... ])
I get the following result:
{ "_id" : "Cotton Pant", "totalQTY" : 2, "count" : 2 }
{ "_id" : "Casual Shirt", "totalQTY" : 11, "count" : 2 }
I'm not sure what you're looking for, it looks like your aggregation pipeline is correct. (Note I changed the Casual Shirt Quantity to be 10 and 1 respectively)
Im having a hard time trying to run some nested queries with a conditional statement of an item inside an array.
this is how my documents looks like.
I would like to get a summary such as sum and average and alarmedCount (count every time Channels.AlarmStatus == "alarmed") of each "Channel" based on Channels.Id. I got sum and average to work but cant get the right query for alarmedCount
{
"_id" : "55df8e4cd8afa4ccer1915ee"
"location" : "1",
"Channels" : [{
"_id" : "55df8e4cdsafa4cc0d1915r1",
"ChannelId" : 1,
"Value" : 14,
"AlarmStatus" : "normal"
},
{
"_id" : "55df8e4cdsafa4cc0d1915r9",
"ChannelId" : 2,
"Value" : 20,
"AlarmStatus" : "alarmed"
},
{
"_id" : "55df8e4cdsafa4cc0d1915re",
"ChannelId" : 3,
"Value" : 10,
"AlarmStatus" : "alarmed"},
]
}
{
"_id" : "55df8e4cd8afa4ccer1915e0"
"location" : "1",
"Channels" : [{
"_id" : "55df8e4cdsafa4cc0d19159",
"ChannelId" : 1,
"Value" : 50,
"AlarmStatus" : "normal"
},
{
"_id" : "55df8e4cdsafa4cc0d1915re",
"ChannelId" : 2,
"Value" : 16,
"AlarmStatus" : "normal"
},
{
"_id" : "55df8e4cdsafa4cc0d1915g7",
"ChannelId" : 3,
"Value" : 9,
"AlarmStatus" : "alarmed"},
]
}
I got it to work to group them and show some calculations
using this aggregate
db.records.aggregate( [
{
"$unwind" : "$Channels"
},
{
"$group" : {
"_id" : "$Channels.Id",
"documentSum" : { "$sum" : "$Channels.Value" },
"documentAvg" : { "$avg" : "$Channels.Value" }
}
}
] )
the result looks like this:
{
"result" : [
{
"_id" : 1,
"documentSum" : 64,
"documentAvg" : 32
},
{
"_id" : 2,
"documentSum" : 36,
"documentAvg" : 18
},
{
"_id" : 3,
"documentSum" : 19,
"documentAvg" : 9.5
},
],
"ok" : 1.0000000000000000
}
I would like to get this type of result
{
"result" : [
{
"_id" : 1,
"documentSum" : 64,
"documentAvg" : 32,
"AlarmedCount" : 0
},
{
"_id" : 2,
"documentSum" : 36,
"documentAvg" : 18,
"AlarmedCount" : 1
},
{
"_id" : 3,
"documentSum" : 19,
"documentAvg" : 9.5,
"AlarmedCount" : 2
}
],
"ok" : 1.0000000000000000
}
Use a project-step before your group-step to convert the field AlarmedStatus to 1 or 0 depending on its value:
$project: {
"Channels.value":"$Channels.Value",
"Channels.AlarmCount":{ $cond: {
if: { $eq: ["$Channels.AlarmedStatus", "alarmed"] },
then: 1,
else: 0 }
}
}
Then sum the newly created field to get the aggregated count:
$group : {
"_id" : "$Channels.Id",
"documentSum" : { "$sum" : "$Channels.Value" },
"documentAvg" : { "$avg" : "$Channels.Value" },
"AlarmCount" : { "$sum" : "$Channels.AlarmCount" }
}
I am doing this query
db.analytics.aggregate([
{
$match: {"event":"USER_SENTIMENT"}
},
{ $group: {
_id: {brand:"$data.brandId",sentiment:"$data.sentiment"},
count: {$sum : 1}
}
},
{ $group: {
_id: "$_id.brand",
sentiments: {$addToSet : {sentiment:"$_id.sentiment", count:"$count"}}
}
}
])
Which generates that :
{
"result" : [
{
"_id" : 57,
"sentiments" : [
{
"sentiment" : "Meh",
"count" : 4
}
]
},
{
"_id" : 376,
"sentiments" : [
{
"sentiment" : "Meh",
"count" : 1
},
{
"sentiment" : "Happy",
"count" : 1
},
{
"sentiment" : "Confused",
"count" : 1
}
]
}
],
"ok" : 1
}
But What I want is that :
[
{
"_id" : 57,
"Meh" : 4
},
{
"_id" : 376,
"Meh" : 1,
"Happy" : 1,
"Confused" : 1
}
]
Any idea on how to transform that? The blocking point for me is to transform a value into a key.