Guy Korland
Guy Korland

Reputation: 9568

Dynamic sub-doc using Mongoose

I'm having a dynamic data model, with couple of static field and the rest are dynamic. e.g.

var item1 = {
    title:'Door',
    price: 30,
    color:{selected:'blue', options:['blue', 'red']}, // dynamic
    material:{selected:'wood', options:['iron', 'wood', 'plastic']}
}

var item2 = {
    title:'T-Shirt',
    price: 5,
    color:{selected:'green', options:['blue', 'green']}, // dynamic 
    size:{selected:'XL', options:['XL', 'L']} // dynamic
}

The fields that are marked as dynamic are not know on schema definition and new once can appear dynamically. The schema I created looks like this:

var itemSchema = mongoose.Schema({
    title: String,
    price: Number
});

It seems like Mongoose stores the dynamic fields but on 'find' these fields return as blobs and toJSON()/toObject() drop them. Is there a way to convert them back to sub-docs?

Upvotes: 3

Views: 5042

Answers (2)

vegetable
vegetable

Reputation: 333

I think that you should use strict option set to false on schema declaration so that other properties added to your document get also saved:

Here, more info: http://mongoosejs.com/docs/guide.html#strict

Regards!

Upvotes: 0

talentedmrjones
talentedmrjones

Reputation: 8161

In my experience Mongoose does not save what is not defined in the schema. Based on your itemSchema, anything other than title or price would not be saved.

Based on the code you've provided I'm assuming that color, size, and material may or may not be present but if they are, they all follow the same format: an object with selected and options keys. So you might want to try Mongoose Subdocuments

var selectionSchema = new Schema({
  selected:String,
  options:Array
});

var itemSchema = mongoose.Schema({
  title: {type:String, required:true},
  price: {type:Number, required:true},
  color: selectionSchema,
  material: selectionSchema,
  size: selectionSchema
});

Notice that color, material, and size keys are not required, this still allows them to be dynamic. If data is present, the key+data will be saved. If no data is present, they key will not be saved either.

UPDATE:

As you mentioned in your comment, you don't know all the dynamic properties upfront. In this case, if you specify a property on the schema as a "blank" object, Mongoose will allow any and all properties on that blank object, like so:

var itemSchema = mongoose.Schema({
  title: {type:String, required:true},
  price: {type:Number, required:true},
  selection:{}
});

Here, the selection key — being a "blank" object — could hold size, color, material, or any other key. They don't need to be known in advance. You could still use the selectionSchema to enforce keys & values of that sub object.

Upvotes: 1

Related Questions