Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to populate nested Mongoose embedded documents

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.

like image 406
rob_hicks Avatar asked Apr 02 '12 18:04

rob_hicks


People also ask

How does populate work Mongoose?

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.

What is path in Mongoose populate?

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).

Does Mongoose populate use lookup?

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.


1 Answers

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);
like image 77
spatical Avatar answered Nov 15 '22 05:11

spatical