Retrieve only the queried element in an object array in MongoDB collection

By : Sebtm
Source: Stackoverflow.com
Question!

Suppose you have the following documents in my collection:

{  
   "_id":ObjectId("562e7c594c12942f08fe4192"),
   "shapes":[  
      {  
         "shape":"square",
         "color":"blue"
      },
      {  
         "shape":"circle",
         "color":"red"
      }
   ]
},
{  
   "_id":ObjectId("562e7c594c12942f08fe4193"),
   "shapes":[  
      {  
         "shape":"square",
         "color":"black"
      },
      {  
         "shape":"circle",
         "color":"green"
      }
   ]
}

Do query:

db.test.find({"shapes.color": "red"}, {"shapes.color": 1})

Or

db.test.find({shapes: {"$elemMatch": {color: "red"}}}, {"shapes.color": 1})

Returns matched document (Document 1), but always with ALL array items in shapes:

{ "shapes": 
  [
    {"shape": "square", "color": "blue"},
    {"shape": "circle", "color": "red"}
  ] 
}

However, I'd like to get the document (Document 1) only with the array that contains color=red:

{ "shapes": 
  [
    {"shape": "circle", "color": "red"}
  ] 
}

How can I do this?

By : Sebtm


Answers

You just need to run query

db.test.find(
{"shapes.color": "red"}, 
{shapes: {$elemMatch: {color: "red"}}});

output of this query is

{
    "_id" : ObjectId("562e7c594c12942f08fe4192"),
    "shapes" : [ 
        {"shape" : "circle", "color" : "red"}
    ]
}

as you expected it'll gives the exact field from array that matches color:'red'.



along with $project it will be more appropriate other wise matching elements will be clubbed together with other elements in document.

db.test.aggregate(
  { "$unwind" : "$shapes" },
  { "$match" : {
     "shapes.color": "red"
  }},
{"$project":{
"_id":1,
"item":1
}}
)


This video can help you solving your question :)
By: admin