I have read and re-read several posts about embedded and linked documents in Mongoose. Based upon what I have read, I have concluded that it would be best to have schema structure similar to the following:
var CategoriesSchema = new Schema({
year : {type: Number, index: true},
make : {type: String, index: true},
model : {type: String, index: true},
body : {type: String, index: true}
});
var ColorsSchema = new Schema({
name : String,
id : String,
surcharge : Number
});
var MaterialsSchema = new Schema({
name : {type: String, index: true},
surcharge : String,
colors : [ColorsSchema]
});
var StyleSchema = new Schema({
name : {type: String, index: true},
surcharge : String,
materials : [MaterialsSchema]
});
var CatalogSchema = new Schema({
name : {type: String, index: true},
referenceId : ObjectId,
pattern : String,
categories : [CategoriesSchema],
description : String,
specifications : String,
price : String,
cost : String,
pattern : String,
thumbnailPath : String,
primaryImagePath : String,
styles : [StyleSchema]
});
mongoose.connect('mongodb://127.0.0.1:27017/sc');
exports.Catalog = mongoose.model('Catalog', CatalogSchema);
The data defined in CategoriesSchema, ColorsSchema and MaterialsSchema won't change very often, if ever. I decided it would be better to have all the data in the Catalog model because while there are multiple categories, colors and materials, there won't be that many and I don't need to find any of them independent of the Catalog.
But I am totally confused about saving data to the model. Here's where I get stumped:
var item = new Catalog;
item.name = "Seat 1003";
item.pattern = "91003";
item.categories.push({year: 1998, make: 'Toyota', model: 'Camry', body: 'sedan' });
item.styles.push({name: 'regular', surcharge: 10.00, materials(?????)});
item.save(function(err){
});
With an nested embedded schema like this, how to I get data into the materials and colors embedded documents?
the .push() method doesn't seem to be available for the nested documents.
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.
Mongoose has a more powerful alternative called populate() , which lets you reference documents in other collections. Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s).
Mongoose's populate() method does not use MongoDB's $lookup behind the scenes. It simply makes another query to the database. Mongoose does not have functionalities that MongoDB does not have. populate() just makes two or more queries.
The array of embedded documents does have the push
method. Simply add Embedded Documents after initially creating the item
:
var item = new Catalog;
item.name = "Seat 1003";
item.pattern = "91003";
item.categories.push({year: 1998, make: 'Toyota', model: 'Camry', body: 'sedan' });
var color = new Color({name: 'color regular', id: '2asdfasdfad', surcharge: 10.00});
var material = new Material({name: 'material regular', surcharge: 10.00});
var style = new Style({name: 'regular', surcharge: 10.00});
then you can push each embedded doc into their parents:
material.colors.push(color);
style.materials.push(material);
item.styles.push(style);
Then you can save the entire object the database as you where already doing:
item.save(function(err){});
That's it! And you have Embedded DocumentArrays.
A few other notes about your code, you have pattern
twice in your Catalog model. And in order to access your other model types, you'll need to also export those:
exports.Catalog = mongoose.model('Catalog', CatalogSchema);
exports.Color = mongoose.model('Colors', ColorsSchema);
exports.Material = mongoose.model('Materials', MaterialsSchema);
exports.Style = mongoose.model('Style', StyleSchema);
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