This syntax is straight from the mongoose documentation on subtypes. However, I've also seen this alternate reference to subdocs. What is the difference?
https://mongoosejs.com/docs/subdocs.html
var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
// Array of subdocuments
children: [childSchema],
// Single nested subdocuments. Caveat: single nested subdocs only work
// in mongoose >= 4.2.0
child: childSchema
});
An alternate type of reference to subdocs
var childSchema = new Schema({ name: 'string' });
mongoose.model('children', childSchema);
var parentSchema = new Schema({
children: {
type: Schema.Types.ObjectId,
ref: 'children'
},
});
The above two syntax are totally different, In one the actual sub-document(children ) is stored in the parent document, but in the other one, a new document is stored in the children collection and only its reference is stored in the parent document.
Case 1:
var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
// Array of subdocuments
children: [childSchema],
// Single nested subdocuments. Caveat: single nested subdocs only work
// in mongoose >= 4.2.0
child: childSchema
});
In this given syntax, parent document will have the child document stored in the parent document as well.
A sample document in the parent sollection will look like this:
{
_id : "parent_random_generated_id"
children :[{ _id : "childid1" , name : "Captain America"},
{ _id : "childid2" , name : "Iron Man"},...],
child : {_id : "childid3" , name : "Thor Odinson"},
...
}
Case 2:
var childSchema = new Schema({ name: 'string' });
mongoose.model('children', childSchema);
var parentSchema = new Schema({
children: {
type: Schema.Types.ObjectId,
ref: 'children'
},
});
In this syntax, child documents will be stored separately, and they reference id (_id) will be stored in the parent document.
Sample documents in this case will look something like this:
// Children documents
{ _id : "childid1" , name : "Captain America"}
{ _id : "childid2" , name : "Iron Man"}
{ _id : "childid3" , name : "Thor Odinson"}
//parent document
{
_id : "parent_random_generated_id"
children :["childid1","childid2",...],
child : "childid3",
...
}
In the second case you can use Mongodb $lookup
operator to populate the sub documents, whenever needed, using mongodb aggregation pipeline
, or use .populate('children')
or .populate('child')
to pupulate the specific child document.
I hope this clarifies your doubt.
I have completed Ravi Shankar Bharti Case 2 with some data writing example. Let's use a book-author scenario:
const authorSchema = new Schema({ name: 'string' });
const authorModel = mongoose.model('authors', authorSchema);
const bookSchema = new Schema({
title: String,
author: {
type: Schema.Types.ObjectId,
ref: 'author'
},
});
const bookModel = mongoose.model('books', bookSchema)
const authorData = { name: "John Doe" }
// Check if author does exists. Insert if not or find if yes
const options = {
upsert: true,
new: true,
setDefaultsOnInsert: true
};
const anAuthor = await authorModel.findOneAndUpdate(authorData, authorData, options)
// Insert a new book with reference to `anAuthor`
const aBook = new bookModel({ title: "MyBook" })
aBook.set({ author: anAuthor })
await aBook.save()
In this syntax, child documents will be stored separately, and they reference id (_id) will be stored in the parent document.
Sample documents in this case will look something like this:
// authors documents
{ _id : "authorId1" , name : "John Doe"}
{ _id : "authorId2" , name : "Iron Man"}
{ _id : "authorId3" , name : "Thor Odinson"}
//books document
{
_id : "parent_random_generated_id"
title: "MyBook",
author : "authorId1",
...
}
And for reading, you can use populate
:
let result = await bookModel.find()
result = await authorModel.populate(result, { path: 'author' })
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