7

I've got a collection were documents have nested arrays, and I would like to select only the lower arrays, is it possible?

I have tried this but it doesn't work:

db.collection.find({},{'family.children.$.toys' :1})

document example

   {
    "id":1000,
    "name": "Bob",
    "surname":"The Builder",
    "family":{
        "size":2,
        "status": "happy",
        "children":[{
            "name":"Jim",
            "school": "St. Mary",
            "toys":[{
                "name":"Lego"
            },
            {
                "name":"Playstation"
            }]
        },
        {
            "name":"Kate",
            "school": "St. Mary",
            "toys":[{
                "name":"Xbox"
            },
            {
                "name":"Barbie"
            }]
        }
        ]
    }
}

Expected result (extract only toys list):

{
_id:1000,
family:{
    childrens:[{
        toys:[{
            name:Lego
        },
        {
            name:Playstation
        }]
    },
    {
        toys:[{
            name:Xbox,
        },
        {
            name:Barbie
        }]
    }
    ]
}}
4
  • One approach would be to use the aggregation framework. I think that would be actually a typical use case for it. The following post will probably guide you a bit more in the direction of a possible solution: stackoverflow.com/questions/15117030/… Commented Sep 22, 2015 at 15:11
  • 1
    Can you at least try to post valid JSON data? Commented Sep 22, 2015 at 15:14
  • He only needs $project from the aggregation framework, which is also available for find(). Commented Sep 22, 2015 at 15:18
  • @user3100115 Now it should be ok Commented Sep 22, 2015 at 15:28

2 Answers 2

15
db.collection.find({},{'id':1, 'family.children.toys' :1, '_id':0})

Sample output:

{
        "id" : 1000,
        "family" : {
                "children" : [
                        {
                                "toys" : [
                                        {
                                                "name" : "Lego"
                                        },
                                        {
                                                "name" : "Playstation"
                                        }
                                ]
                        },
                        {
                                "toys" : [
                                        {
                                                "name" : "Xbox"
                                        },
                                        {
                                                "name" : "Barbie"
                                        }
                                ]
                        }
                ]
        }
}
Sign up to request clarification or add additional context in comments.

2 Comments

This works, and it was pretty simple! I was sure that I had already tried it, so I posted the question :D. Thanks
this works. How can I add one more field "_id" of each "toy" along with its "name" ?
2

You can also do this with aggregation. You use the $map operator to return only the toys field.

db.collection.aggregate([{ 
    "$project": { 
        "family.childrens": { 
            "$map": { 
                "input": "$family.children",
                "as": "f", 
                "in": { "toys": "$$f.toys" }
            }
        }
     }}
 ])

2 Comments

The accepted answer looks more direct, there is any performance reason why we should use this aggregation framework version?
@MQ87 No the accepted answer is the best way to do this here(I even upvoted the answer). I added this answer so you know because sometimes aggregation is the only way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.