I will use the example from here
{ _id: 1, zipcode: 63109, students: [ { name: "john", school: 102, age: 10 }, { name: "jess", school: 102, age: 11 }, { name: "jeff", school: 108, age: 15 } ] } { _id: 2, zipcode: 63110, students: [ { name: "ajax", school: 100, age: 7 }, { name: "achilles", school: 100, age: 8 }, ] } { _id: 3, zipcode: 63109, students: [ { name: "ajax", school: 100, age: 7 }, { name: "achilles", school: 100, age: 8 }, ] } { _id: 4, zipcode: 63109, students: [ { name: "barney", school: 102, age: 7 }, ] }
If I run
db.schools.find( { zipcode: 63109 }, { students: { $elemMatch: { school: 102 } } } )
It will give the first result of each array. Naming this:
{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } { "_id" : 3 } { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
How can I make it return all the object of the array (and not only the first) that match the criteria? Meaning this:
{ _id: 1, students: [ { name: "john", school: 102, age: 10 }, { name: "jess", school: 102, age: 11 } ] } { _id: 3 } {_id: 4, students: [ { name: "barney", school: 102, age: 7 }]}
In order to return multiple subdocuments, you're going to need to use the aggregation framework. This will return all of the subdocuments you're looking for:
db.zip.aggregate( {$match: {zipcode: 63109}}, {$unwind: "$students"}, {$match: {"students.school": 102}} )
You can do various things to get different output, but this will return:
{ "result" : [ { "_id" : 1, "zipcode" : 63109, "students" : { "name" : "john", "school" : 102, "age" : 10 } }, { "_id" : 1, "zipcode" : 63109, "students" : { "name" : "jess", "school" : 102, "age" : 11 } }, { "_id" : 4, "zipcode" : 63109, "students" : { "name" : "barney", "school" : 102, "age" : 7 } } ], "ok" : 1 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With