How to filter and map array of documents in MongoDB query?

Viewed 19952

So I've got these documents in my people collection:

{
        "_id" : ObjectId("595c0630939a8ae59053a9c3"),
        "name" : "John Smith",
        "age" : 37,
        "location" : "San Francisco, CA",
        "hobbies" : [
                {
                        "name" : "Cooking",
                        "type" : "Indoor",
                        "regular" : true
                },
                {
                        "name" : "Baseball",
                        "type" : "Outdoor",
                        "regular" : false
                }
        ]
}
{
        "_id" : ObjectId("595c06b7939a8ae59053a9c4"),
        "name" : "Miranda Thompson",
        "age" : 26,
        "location" : "Modesto, CA",
        "hobbies" : [
                {
                        "name" : "Lego building",
                        "type" : "Indoor",
                        "regular" : false
                },
                {
                        "name" : "Yoga",
                        "type" : "Indoor",
                        "regular" : false
                }
        ]
}
{
        "_id" : ObjectId("595c078e939a8ae59053a9c5"),
        "name" : "Shelly Simon",
        "age" : 26,
        "location" : "Salt Lake City, UT",
        "hobbies" : [
                {
                        "name" : "Hunting",
                        "type" : "Outdoor",
                        "regular" : false
                },
                {
                        "name" : "Soccer",
                        "type" : "Outdoor",
                        "regular" : true
                }
        ]
}

I am trying to filter my "hobbies" array only to regular hobbies AND project the fields _id, name, age and hobby's name and type.

I want my output to be something like this:

{
        "_id" : ObjectId("595c0630939a8ae59053a9c3"),
        "name" : "John Smith",
        "age" : 37,
        "hobbies" : [
                {
                        "name" : "Cooking",
                        "type" : "Indoor"
                }
        ]
}
{
        "_id" : ObjectId("595c06b7939a8ae59053a9c4"),
        "name" : "Miranda Thompson",
        "age" : 26,
        "hobbies" : []
}
{
        "_id" : ObjectId("595c078e939a8ae59053a9c5"),
        "name" : "Shelly Simon",
        "age" : 26,
        "hobbies" : [
                {
                        "name" : "Soccer",
                        "type" : "Outdoor"
                }
        ]
}

Well... I can achieve this output using this command in mongo shell:

db.people.aggregate([
    { 
        $project: { 
            hobbies: { 
                $filter: { 
                    input: "$hobbies", 
                    as: "hobby", 
                    cond: { $eq: ["$$hobby.regular", true] } 
                }
            },
            name: 1,
            age: 1
        }
    }, 
    { 
        $project: { 
            "hobbies.name": 1, 
            "hobbies.type": 1, 
            name: 1,
            age: 1
        } 
    }
])

As you can see, I had to use two $project operators in sequence and I think this smells bad.

Is there a way to achieve the same result with another query that does not use the same operator twice and in sequence?

1 Answers
Related