1

I have created a collection which has sub collection data. I want to filter from sub collection with a key.

Here is my document:

{
    "_id" : ObjectId("5758098356e3930537af15dd"),
    "manpower_data" : [ 
        {
            "_id" : ObjectId("5758098356e3930537af15de"),
            "created" : ISODate("2016-06-08T12:03:15.387Z"),            
            "designation" : "Visiting Evaluator",            
            "evaluatorContactNumber" : "987654321",            
            "evaluatorName" : "Dumy User1",
            "dealerCodeFor" : "ZSAE876",
            "region" : "Gurgaon"
        }, 
        {
            "_id" : ObjectId("5758098356e3930537af15de"),
            "created" : ISODate("2016-06-08T12:03:15.387Z"),            
            "designation" : "Resident Evaluator",            
            "evaluatorContactNumber" : "987654321",            
            "evaluatorName" : "Dumy User2",
            "dealerCodeFor" : "ZSAE877",
            "region" : "Delhi"
        }
    ]
}

When I run this query

db.mycollection.find({"manpower_data.dealerCodeFor":"ZSAE876"});

It returns me all two sub document but I want to get only those manpower data which has matching dealerCodeFor.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Anuranjan Pandey
  • 132
  • 2
  • 11

2 Answers2

3

To filter array elements, query projection phase with $elemMatch need to be executed. Please see example below:

db.collection.find({
    "manpower_data.dealerCodeFor" : "ZSAE876"
}, {
    manpower_data : {
        $elemMatch : {
            dealerCodeFor : "ZSAE876"
        }
    }
})
profesor79
  • 9,213
  • 3
  • 31
  • 52
2

You can use $filter of aggregate-mongodb to achieve this.

Try the following:-

db.collection.aggregate([
{ 
    "$match": {"manpower_data.dealerCodeFor":"ZSAE876"}
},
{
    "$project": {
        "manpower_data": {
            "$filter": {
                "input": "$manpower_data",
                "as": "o",
                "cond": {  
                    "$eq": ["$$o.dealerCodeFor", "ZSAE876"]
                }
            }
        }
    }
}])

By running the above query, manpower_data will return only the objects, which matches your condition.

EDIT:-

For version less than 2.6.x, try following query:-

db.collection.aggregate([
{ 
    "$match": {"manpower_data.dealerCodeFor":"ZSAE876"}
},  
{ "$unwind": "$manpower_data" },
{ 
    "$match": {"manpower_data.dealerCodeFor":"ZSAE876"}
},
{
    "$group": {
        "$_id": "$_id",
        "manpower_data": { "$push": "$manpower_data" }
    }
}])
Shrabanee
  • 2,706
  • 1
  • 18
  • 30