aggregation and display details in mongodb - mongodb

I have been learning MongoDB, while doing so I tried to implement the aggregation property for my database collection. I grouped the details of the employee based on their age and by using match function, my question is it possible to display the other key-value once they pass the age criteria?
db.employee.aggregate([
{ $match: { age: { $gte: 23 } } },
{
$group: {
_id:'$age',
total: { $sum: 1 },
name: { $addToSet: '$name' }
}
}
])
and the output was like this
{ "_id" : 27, "total" : 2, "name" : [ "indhu", "logesh" ] }
{ "_id" : 26, "total" : 1, "name" : [ "keerthana" ] }
{ "_id" : 25, "total" : 1, "name" : [ "sneha" ] }
{ "_id" : 24, "total" : 1, "name" : [ "dhiva" ] }
{ "_id" : 23, "total" : 1, "name" : [ "elango" ] }
where _id denotes their age.

Related

how to show a specific field in array using $project in mongodb

I have a database that contains information about flights. I'm trying to find the category that has the least minutes of delays. I managed to find and show the number of the minimum minutes of the category but not the category itself.
I've tried to put ":true" after each field to show it
db.delayData.aggregate([{
$group: {
"_id": "$carrier",
"arr_sum": {
$sum: "$arr_delay"
},
"carrier_sum": {
$sum: "$carrier_delay"
},
"weather_sum": {
$sum: "$weather_delay"
},
"nas_sum": {
$sum: "$nas_delay"
},
"sec_sum": {
$sum: "$security_delay"
},
"late_air_sum": {
$sum: "$late_aircraft_delay"
}
}
},
{
$project {
"min_delay_category": {
$min["$arr_sum", "$carrier_sum", "$weather_sum", "$nas_sum", "$sec_sum", "$late_air_sum"]
}
}
]).pretty()
I want to have something like that:
{ "_id" : "VX", "min_delay_category" : 1449, "sec_sum"... }
I've tried to write:
..."$sec_sum":1,"$late_air_sum":1]
but the error message is:
"missing ] after element list"
when I wrote:
...{"sec_sum":1},{"late_air_sum":1}]
I don't have error message but it will give me the least second result, not the first one.
for example:
{ "_id" : "VX", "min_delay_category" : 69081 }
but the true result for "VX" is 1449
The following query can get us the expected output:
db.collection.aggregate([
{
$project:{
"carrier":1,
"category.arr_delay":"$arr_delay",
"category.carrier_delay":"$carrier_delay",
"category.weather_delay":"$weather_delay",
"category.nas_delay":"$nas_delay",
"category.security_delay":"$security_delay",
"category.late_aircraft_delay":"$late_aircraft_delay"
}
},
{
$project:{
"carrier":1,
"categories":{
$objectToArray:"$category"
}
}
},
{
$unwind:"$categories"
},
{
$group:{
"_id":{
"carrier":"$carrier",
"category":"$categories.k"
},
"carrier":{
$first:"$carrier"
},
"category":{
$first:"$categories.k"
},
"total_delay":{
$sum:"$categories.v"
}
}
},
{
$sort:{
"total_delay":1
}
},
{
$group:{
"_id": "$carrier",
"carrier":{
$first:"$carrier"
},
"category":{
$first:"$category"
},
"minimum_delay":{
$first:"$total_delay"
}
}
},
{
$project:{
"_id":0
}
}
]).pretty();
Data set:
{
"_id" : ObjectId("5d5b5058435c7584459b7bae"),
"year" : 2003,
"month" : 6,
"carrier" : "AA",
"carrier_name" : "American Airlines Inc.",
"airport" : "ABQ",
"airport_name" : "Albuquerque, NM: Albuquerque International Sunport",
"arr_flights" : 307,
"arr_del15" : 56,
"carrier_ct" : 14.68,
"weather_ct" : 10.79,
"nas_ct" : 19.09,
"security_ct" : 1.48,
"late_aircraft_ct" : 9.96,
"arr_cancelled" : 1,
"arr_diverted" : 1,
"arr_delay" : 2530,
"carrier_delay" : 510,
"weather_delay" : 621,
"nas_delay" : 676,
"security_delay" : 25,
"late_aircraft_delay" : 698,
"" : ""
},
{
"_id" : ObjectId("5d5b5058435c7584459b7bbe"),
"year" : 2003,
"month" : 6,
"carrier" : "AA",
"carrier_name" : "American Airlines Inc.",
"airport" : "ABQ",
"airport_name" : "Albuquerque, NM: Albuquerque International Sunport",
"arr_flights" : 307,
"arr_del15" : 56,
"carrier_ct" : 14.68,
"weather_ct" : 10.79,
"nas_ct" : 19.09,
"security_ct" : 1.48,
"late_aircraft_ct" : 9.96,
"arr_cancelled" : 1,
"arr_diverted" : 1,
"arr_delay" : 2530,
"carrier_delay" : 510,
"weather_delay" : 621,
"nas_delay" : 676,
"security_delay" : 2512,
"late_aircraft_delay" : 698,
"" : ""
}
Output:
{ "carrier" : "AA", "category" : "carrier_delay", "minimum_delay" : 1020 }
Aggregation stage details:
STAGE I: Projecting all delays as a part of category document
STAGE II: Converting category into an array of key-value pair
where 'k' is delay type and 'v' is a delay
STAGE III: Unwinding the prepared array
STAGE IV: Grouping on the basis of carrier and delay type(k) and summing up delay for each type
STAGE V: Sorting on total calculated delay in ascending order
STAGE VI: Grouping on carrier and fetching the first document
which holds the minimum delay

mongodb find the document by id and then group the result based on name field

I have a collection with multiple documents like
{
"_id" : ObjectId("5a64d076bfd103df081967ae"),
"status" : "",
"Number" : 53,
"values" : [
{
"date" : "2015-05-18",
"value" : 12.41
},
{
"date" : "2015-05-19",
"value" : 12.45
},
],
"Name" : "ABC Banking",
"scheme":"ABC1",
"createdDate" : "21-01-2018"
}
{
"_id" : ObjectId("5a64d076bfd103df081967ae"),
"status" : "",
"Number" : 53,
"values" : [
{
"date" : "2015-05-18",
"value" : 13.41
},
{
"date" : "2015-05-19",
"value" : 13.45
},
],
"Name" : "ABC Banking",
"scheme":"ABC2",
"createdDate" : "21-01-2018"
}
I am Querying collection based on Number field like
db.getCollection('mfhistories').find({'Number':53})
to get all the documents with this Number.
Now I want to group all the collection with Name 'ABC Banking' into an array. so that I will get result based on Name.
so the result should be like
{
"Name":"ABC Banking",
[
{
"_id" : ObjectId("5a64d076bfd103df081967ae"),
"status" : "",
"Number" : 53,
"values" : [
{
"date" : "2015-05-18",
"value" : 13.41
},
{
"date" : "2015-05-19",
"value" : 13.45
},
],
"scheme":"ABC1",
"createdDate" : "21-01-2018"
},
{
"_id" : ObjectId("5a64d076bfd103df081967ae"),
"status" : "",
"Number" : 53,
"values" : [
{
"date" : "2015-05-18",
"value" : 13.41
},
{
"date" : "2015-05-19",
"value" : 13.45
}
],
"scheme":"ABC2",
"createdDate" : "21-01-2018"
}
]
}
Please help..
Thanks,
J
You can use Aggregation Framework for that:
db.col.aggregate([
{
$match: { Number: 53, Name: "ABC Banking" }
},
{
$group: {
_id: "$Name",
docs: { $push: "$$ROOT" }
}
},
{
$project: {
Name: "$_id",
_id: 0,
docs: 1
}
}
])
$$ROOT is a special variable which captures entire document. More here.
db.mfhistories.aggregate(
// Pipeline
[
// Stage 1
{
$match: {
Number: 53
}
},
// Stage 2
{
$group: {
_id: {
Name: '$Name'
},
docObj: {
$addToSet: '$$CURRENT'
}
}
},
// Stage 3
{
$project: {
Name: '$_id.Name',
docObj: 1,
_id: 0
}
}
]
);

How to find minimum value in aggregate $group

I have below collection structure and I want to find minimum score for each student.
>db.students.findOne()
{
"_id" : 0,
"name" : "aimee Zank",
"scores" : [
{
"type" : "exam",
"score" : 1.463179736705023
},
{
"type" : "quiz",
"score" : 11.78273309957772
},
{
"type" : "homework",
"score" : 6.676176060654615
},
{
"type" : "homework",
"score" : 35.8740349954354
}
]
}
I use below aggregate command
db.students.aggregate([
{
$group: {_id: "$_id" , min: {$min: '$scores.score'}}
}
])
below is the output:
{ "_id" : 199, "min" : [ 82.11742562118049, 49.61295450928224, 28.86823689842918, 5.861613903793295 ] }
{ "_id" : 198, "min" : [ 11.9075674046519, 20.51879961777022, 55.85952928204192, 64.85650354990375 ] }
{ "_id" : 95, "min" : [ 8.58858127638702, 88.40377630359677, 25.71387474240768, 23.73786528217532 ] }
{ "_id" : 11, "min" : [ 78.42617835651868, 82.58372817930675, 87.49924733328717, 15.81264595052612 ] }
{ "_id" : 94, "min" : [ 6.867644836612586, 63.4908039680606, 85.41865347441522, 26.82623527074511 ] }
it returns all scores for each student instead of the minimum one. What wrong with my query command? I am using mongo 3.4.
After some searching, I found that the solution is to add $unwind on scores.score. The complete command is:
stus = db.students.aggregate([
{
"$unwind": "$scores"
},
{
$group: {_id: "$_id" , minScore: {$min: '$scores.score'}}
}
])

Aggregating an array of values in MongoDB

I have an array of values I want to group by the id of, and get the sum of all the values. Currently I'm trying:
db.entries.aggregate(
[
{ $match: {"user": "John" } },
{ "$unwind": '$games'},
{ $group: {
"_id": "$games.id",
"score": { "$sum": "$games.score"} }},
])
The data looks like:
{
"user":"john",
"games":[
{
"id":123,
"score":123
}
]
},
{
"user":"john",
"games":[
{
"id":123,
"score":123
}
]
},
{
"user":"john",
"games":[
{
"id":256,
"score":256
}
]
}
In this example, for "John" I would like to get the total of all the unique game scores. I should get (123 + 256) in this example.
However, right now I'm getting the sum of individual games, not all of them as a total.
I have here:
> db.entries.find();
{ "_id" : ObjectId("56a9610cca390d7e14a54486"), "user" : "john", "games" : [ { "id" : 123, "score" : 123 } ] }
{ "_id" : ObjectId("56a9610cca390d7e14a54487"), "user" : "john", "games" : [ { "id" : 123, "score" : 123 } ] }
{ "_id" : ObjectId("56a9610cca390d7e14a54488"), "user" : "john", "games" : [ { "id" : 256, "score" : 256 } ] }
> db.entries.aggregate([ {$match: {user: "john"}}, {$unwind: "$games"}, {$group: {_id: "$games.id", score: {$sum: "$games.score"}}} ]);
{ "_id" : 256, "score" : 256 }
{ "_id" : 123, "score" : 246 }
What’s the problem?

MongoDB aggregate Query for sum

I have a collection as follows
{ "_id" : 0, "name" : "aimee Zank", "scores" :
[
{ "type" : "exam", "score" : 1.463179736705023 },
{ "type" : "quiz", "score" : 11.78273309957772 },
{ "type" : "homework", "score" : 6.676176060654615}
] }
{"_id" : 1, "name" : "Aurelia Menendez", "scores" :
[
{ "type" : "exam", "score" : 60.06045071030959 },
{ "type" : "quiz", "score" : 52.79790691903873 },
{ "type" : "homework", "score" : 71.761334391544 }
] }
{"_id" : 2, "name" : "Corliss Zuk", "scores" :
[
{ "type" : "exam", "score" : 67.03077096065002 },
{ "type" : "quiz", "score" : 6.301851677835235 },
{ "type" : "homework", "score" : 20.18160621941858}
] }
Now i want the sum of all the scores of each type for respective students
for example for student aimee zank i want the sum of scores for exam+quiz+homework.
I have tried this
db.collection.aggregate(
[
{
$group:
{
_id: "$name",
total: { $sum: "$scores.score" },
}
}
]
)
and this
db.scores.aggregate(
[
{ $project: { name: 1, total: { $add: [ "$scores.score" ] } } }
]
)
But i could not find a solution
Can someone please help me with the query?
After finding no help on stackoverflow and only discouraging people in the group, i have found a solution on my own and it is just one part of the solution of i was searching for:
db.scores.aggregate(
[
{ $unwind : "$scores"},
{ $group:
{
_id: "$name",
total: { $sum: "$scores.score" }
}
}
]
)