Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose - finding subdocuments by criteria

I've just got stuck with this problem. I've got two Mongoose schemas:

var childrenSchema = mongoose.Schema({     name: {         type: String     },     age: {         type: Number,         min: 0     } });  var parentSchema = mongoose.Schema({     name : {         type: String     },     children: [childrenSchema] }); 

Question is, how to fetch all subdocuments (in this case, childrenSchema objects) from every parent document? Let's suppose I have some data:

var parents = [     { name: "John Smith",     children: [         { name: "Peter", age: 2 }, { name: "Margaret", age: 20 }     ]},     { name: "Another Smith",     children: [         { name: "Martha", age: 10 }, { name: "John", age: 22 }     ]} ]; 

I would like to retrieve - in a single query - all children older than 18. Is it possible? Every answer will be appreciated, thanks!

like image 633
Kuba T Avatar asked May 30 '13 20:05

Kuba T


People also ask

What is the __ V field in Mongoose?

The __v field is called the version key. It describes the internal revision of a document. This __v field is used to track the revisions of a document. By default, its value is zero ( __v:0 ). If you don't want to use this version key you can use the versionKey: false as mongoose.

What is the difference between id and _ID in Mongoose?

So, basically, the id getter returns a string representation of the document's _id (which is added to all MongoDB documents by default and have a default type of ObjectId ). Regarding what's better for referencing, that depends entirely on the context (i.e., do you want an ObjectId or a string ).

What is skip and limit in Mongoose?

The limit method will be used to return the maximum number of results from the collection, while the skip method is used to skip the number of documents from the collection in MongoDB. If we have one collection name as a student, student collection contains a hundred documents in it.

What is path in Mongoose populate?

Mongoose Populate() Method In MongoDB, Population is the process of replacing the specified path in the document of one collection with the actual document from the other collection.


1 Answers

You can use $elemMatch as a query-projection operator in the most recent MongoDB versions. From the mongo shell:

db.parents.find(     {'children.age': {$gte: 18}},     {children:{$elemMatch:{age: {$gte: 18}}}}) 

This filters younger children's documents out of the children array:

{ "_id" : ..., "children" : [ { "name" : "Margaret", "age" : 20 } ] } { "_id" : ..., "children" : [ { "name" : "John", "age" : 22 } ] } 

As you can see, children are still grouped inside their parent documents. MongoDB queries return documents from collections. You can use the aggregation framework's $unwind method to split them into separate documents:

> db.parents.aggregate({     $match: {'children.age': {$gte: 18}} }, {     $unwind: '$children' }, {     $match: {'children.age': {$gte: 18}} }, {     $project: {         name: '$children.name',         age:'$children.age'     } }) {     "result" : [         {             "_id" : ObjectId("51a7bf04dacca8ba98434eb5"),             "name" : "Margaret",             "age" : 20         },         {             "_id" : ObjectId("51a7bf04dacca8ba98434eb6"),             "name" : "John",             "age" : 22         }     ],     "ok" : 1 } 

I repeat the $match clause for performance: the first time through it eliminates parents with no children at least 18 years old, so the $unwind only considers useful documents. The second $match removes $unwind output that doesn't match, and the $project hoists children's info from subdocuments to the top level.

like image 177
A. Jesse Jiryu Davis Avatar answered Sep 18 '22 00:09

A. Jesse Jiryu Davis