Reputation: 1205
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'
},
});
Upvotes: 6
Views: 3927
Reputation: 6691
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' })
Upvotes: 2
Reputation: 1318
Difference is pretty simple. The former one where you are just defining schema for child won't create a separate collection for the children in the database instead you will embed the whole child document in the parent.
And in the later one you are defining a model for the child schema by calling mongoose.model which creates a separate collection of children in the database and you can then reference child documents in the parent document without embedding the whole child document in the parent by just adding the child _id.
Upvotes: 1
Reputation: 9268
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.
Upvotes: 4