Is it possible to have an array of alternative subdocument schemas in mongoose?
For instance, take this made up scenario: if i have a main schema for a person and i have a field called vehicles of type array, i want to be able to define sub document schemas, but for each vehicle type (car, motorbike, bike, bus etc etc ) :
var car = new mongoose.Schema({
make: { type: String, required: true, default: 'Ford', trim: true },
model: { type: String, trim: true },
wheels: Number,
});
var motorbike = new mongoose.Schema({
make: { type: String, required: true, default: 'Honda', trim: true },
model: { type: String, trim: true },
seats: Number,
});
var bike = new mongoose.Schema({
make: { type: String, required: true, default: 'MuddyFox', trim: true },
model: { type: String, trim: true },
lights: Number,
});
var bus = new mongoose.Schema({
make: { type: String, required: true, default: 'MAN', trim: true },
model: { type: String, trim: true },
dents: Number,
});
/* person */
var person = new mongoose.Schema({
name: { type: String, required: true, default: 'Joe Bloggs', trim: true },
timeCreated: { type: Date, required: true, default: Date.now },
vehicles: [car, motorbike, bike, bus] /* this is what i want to do */
});
db.model('person', person);
Note the person schema.
So that person can have any of those vehicles, but the data for each vehicle is still validated against it's own schema.
Thanks in advance
There is a mongoose plugin called mongoose-schema-extend, that will allow you to enable Schema Inheritance for Mongoose, and basically I think, you are looking for this functionality.
Please check the github project:
You can create a Vehicle schema, add it as an array to the Person schema, and extend the Vehicle for your different type of vehicles.
I couldn't find any examples of multiple embedded documents being passed as an array.
Perhaps you could rejig things like this:
var car = new mongoose.Schema({
make: { type: String, required: true, default: 'Ford', trim: true },
model: { type: String, trim: true },
wheels: Number,
});
var motorbike = new mongoose.Schema({
make: { type: String, required: true, default: 'Honda', trim: true },
model: { type: String, trim: true },
seats: Number,
});
var bike = new mongoose.Schema({
make: { type: String, required: true, default: 'MuddyFox', trim: true },
model: { type: String, trim: true },
lights: Number,
});
var bus = new mongoose.Schema({
make: { type: String, required: true, default: 'MAN', trim: true },
model: { type: String, trim: true },
dents: Number,
});
var transport = new mongoose.Schema({
car: [car],
motorbike: [motorbike],
bike: [bike],
bus: [bus]
});
/* person */
var person = new mongoose.Schema({
name: { type: String, required: true, default: 'Joe Bloggs', trim: true },
timeCreated: { type: Date, required: true, default: Date.now },
vehicles: [transport]
});
db.model('person', person);
If that doesn't work, then as described in this SO question you can use mongoose populate. This method is now more effective following the addition of deep population was added in Mongoose Deep 3.6.
So you could do soemthing like:
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }]
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
There's also a mongoose plugin to aid with this functionality called mongoose-deep-populate which is very up-to-date.