How to define varying attributes for a product system in mongoose (node.js) How to define varying attributes for a product system in mongoose (node.js) mongoose mongoose

How to define varying attributes for a product system in mongoose (node.js)


An easy way to add inheritance to your Mongoose Schemas is to use Discriminators. This will allow you to create a parent Schema that can store attributes that are across all your products such as title, price, and images. You can then create child Schemas that will contain attributes specific to a product type such as Electronics and Clothing. For example in the Electronics Schema you can add attributes for cpu and ram that will not be present in the Clothing Schema.

Here is a basic example of how I set this up using Node and Mongoose.

Node/Javascript

var mongoose = require('mongoose');mongoose.connect('mongodb://localhost/test');// When you create a Electronic Product, it will set the type to Eletronic. var options = { discriminatorKey: 'type' };// parent Product schema.var productSchema = new mongoose.Schema({ name: String, price: Number }, options);var Product = mongoose.model('Product', productSchema);// child Electronic schema.var ElectronicProduct = Product.discriminator('Electronic', new mongoose.Schema({ cpu: Number }, options));var computer = new ElectronicProduct({ name: 'computer', price: 100, cpu: 5 });computer.save();// child Clothing schema. var ClothingProduct = Product.discriminator('Clothing', new mongoose.Schema({ size: String }, options));var shirt = new ClothingProduct({ name: 'shirt', price: 50, size: 'Small' });shirt.save();

If you log the objects that are saved they should look like

{ _id: 564b55983e5eec1ce2a44038,  type: 'Electronic',  cpu: 5,  price: 100,  name: 'computer' }{ _id: 564b55983e5eec1ce2a44039,  type: 'Clothing',  size: 'Small',  price: 50,  name: 'shirt' }

When you attempt to access attributes that are not in the Product schema, it would be good practice to check if the attribute exists before trying to access it.


If what you are asking is how to approach the schema I would say make your model attributes an array of objects or of type mixed

http://mongoosejs.com/docs/schematypes.html

Because you can have many possible options for attributes it's impossible to know all of them in advance. Maybe you want the user to define the name of the attribute(the key) and the value as well. Then once you get an object you can use a for inloop to use the key as the label and the value.

example:

var attributes = [];for ( attr in item.attributes ) {    //do something with the key=>value pair    attributes.push({        label: attr,        value: item.attributes[attr]    }); }//iterate through the new array to display your item attributes


For this dynamic data scenario i would prefer keeping attributes as empty object in the Mongoose Model, so that you can use varying attributes for each documents.

Model

var mongoose = require('mongoose');Schema = mongoose.Schema;var productSchema = new mongoose.Schema({    title:{type:String,required}, // Common Attributes    price:{type:Number,required}, // Common Attributes    images:[buffer], // Common Attributes    //Other Common Attributes goes here    attributes:{} // Empty attributes object which can vary for each product.});var Product = mongoose.model('Product', productSchema);

You can use the attributes object to specify the varying attributes for the specific product.

Controller

var computer = new Product({ title: 'Computer', price: 1000, attributes:{   year:2000,   cpu:'test',   power:'75 RMS'  // Other Attributes goes here. }});var shirt = new Product({ title: 'T-Shirt', price: 999, attributes:{   size:30,   color:'black'  // Other Attributes goes here. }});

Reference:

http://mongoosejs.com/docs/schematypes.html ( Look for the Mixed Data Type)

Note:

There are other ways to create this schema, one way is to have attributes as embedded document with all the combinations of attributes and can keep the value as null if it is not applicable.

Hope this helps.