Querying sub-documents and sub-sub-documents in Mongoose
FInding sub-docs in mongoose the first time may seem a bit hard or just confusing. That's why I decided to write this.
Creating the Schemas
var likesSchema = new Schema({
username: 'string'
})
var statusSchema = new Schema({
text: 'string',
likes: [likesSchema]
})
var userSchema = new Schema({
username: 'string',
status: [statusSchema]
})
As you can see we embedded the likesSchema inside the statusSchema which is embedded inside the userSchema. The problem with sub-docs is that they are not saved individually, they are saved there the parent Schema is saved, so if you need to use the sub-docs individually this may not be the right approach for you.
Creating some users, sub-docs and sub-sub-docs
var User = mongoose.model('User', userSchema);
var user = new User({
username: 'derp',
status: [{text: 'Hello world!'}]
})
var friend = new User({
username: 'goku',
status: [{text: 'Kamehameha!!!'}]
})
user.save(callback);
friend.save(callback);
This will create two users. After this comes the interesting part: Querying the sub-docs, creating them and modifying them. As well with the sub-sub-docs
Querying
//If you know the sub-doc position in the array it is pretty simple to query it
var subdoc = user.status[0];
console.log(subdoc.text); //This will output: Hello world!
//If you know its id it is also really simple
var subdoc = user.status.id(id); //where id is the sub-doc _id
/*
If you only know the text it is a little bit more complicated
*/
User.findOne({'status.text': 'Kamehameha!!!'}, function(err, the_user){
if(err)console.log(err)
if(the_user){
console.log(the_user.username); //goku
}
})
Adding sub-sub-docs
subdoc.likes.push({
username: friend.username
})
subdoc.save(callback);
//It is really easy as pie!
Query sub-sub-docs
This is were trouble comes, because there is not really a way in mongoose to query them. You can use the position in the array if you know it, but you can't really keep track of this.
Remember it is an array so you can do this to query them:
for(i in subdoc.likes){
//username is the variable of the username of the like you want to find
if(likes[i].username == username){
//do something cool here
}
}
And that's it!
Written by Dominik García
Related protips
5 Responses
How do you go about updating a subdocument given the parent id and the child id?
You find the parent by his id and then you go:
vat suddoc = Parent.children.id(childrenid);
if(err) console.log(err);
if(the_user){
console.log(the_user.username); //goku
}
yikes.
I exactly did what has been mentioned, but seems to have an error.
TypeError: Object [object Object],[object Object],[object Object] has no method 'id'
Could you please help me out? Thanks in advance.
can I see your code or some of it?