user3108836
user3108836

Reputation: 21

MongoDB aggregation pipeline

I have this type of documents:

collection:People
{name:"George", grade:5, school:"MathHighSchool"}

and many more examples. I need a query that finds all people who: study in the MathHighSchool (so we have db.people.aggregate({$match:{school:"MathHighSchool"}},....)

and then group them by their grades, as it shows the number of people with grade <3 number of people with grade between 3 and 5 and number of people with grade > 5. Any ideas?

Upvotes: 0

Views: 1387

Answers (2)

Dharmendra Kumar
Dharmendra Kumar

Reputation: 1

We can also achieve this solution using switch case in mongo and if condition also, here is a little approach to achieve the solution.

Query:

db.people.aggregate([
    {$match:{"school":"MathHighSchool"}},
    {$project:{"school":1,"div": { $switch:
    {
        branches: [
        {
            case: { $lte : ["$grade", 3 ] },
            then: "less than or equal to 3"
        },
        {
            case: { $and : [ { $gt : ["$grade", 3 ] },
            { $lt : [ "$grade", 5 ] } ] },
            then: "between 3 and 5"
        },
        {
            case: { $gte : [ "$grade", 5] },
            then: "greater than or equal to 5"
        }],
    }}}},
    {$group:{"_id":"$div","count":{$sum:1}}}
]);

Result:

{ 
    "_id" : "between 3 and 5", 
    "count" : 1.0
}
{ 
    "_id" : "less than or equal to 3", 
    "count" : 2.0
}
{ 
    "_id" : "greater than or equal to 5", 
    "count" : 3.0
}

Please Visit here for more detail https://beingcodeexpert.blogspot.com/2021/02/switch-conditional-operator-in-mongodb.html

Upvotes: 0

Stennie
Stennie

Reputation: 65403

In order to conditionally sum matches in your $group pipeline step, you need to use the $cond operator.

Test data set up:

db.people.insert([
    {name:"George", grade:5, school:"MathHighSchool"},
    {name:"John", grade:4, school:"MathHighSchool"},
    {name:"Paul", grade:3, school:"MathHighSchool"},
    {name:"Ringo", grade:5, school:"MathHighSchool"},
    {name:"Johnny", grade:2, school:"MathHighSchool"},
    {name:"Joshua", grade:7, school:"MathHighSchool"},
])

Assuming you just want the counts, here is an example aggregation (tested with MongoDB 2.4.8):

db.people.aggregate(
    { $match: {
        school : 'MathHighSchool'
    }},
    { $group: {
        _id: "$school",

        // Add up matches less than grade 3
        low: { $sum: { $cond: [ {$lt: ["$grade", 3] }, 1, 0] }},

        // Add up matches between 3 and 5 (inclusive)
        medium: { $sum: { $cond:[
            { $and: [ {$gte: ["$grade", 3]}, {$lte: ["$grade", 5]} ] }, 1, 0]
        }},

        // Add up matches greater than grade 5
        high: { $sum: { $cond: [ {$gt: ["$grade", 5] }, 1, 0] }},

    }}
)

Result:

{
    "result" : [
        {
            "_id" : "MathHighSchool",
            "low" : 1,
            "medium" : 4,
            "high" : 1
        }
    ],
    "ok" : 1
}

Upvotes: 4

Related Questions