Building on the answer to this question, Nested arrays in Mongoose
I am wondering if there is a way to have an array in a mongoose schema that will only accept one of two types of Schema defined documents as elements in the array. What do I mean by this? Consider a schema defined as...
var MyDocSchema = new Schema({
name: String,
stuff: [Stuff],
});
Where stuff is defined as
var Stuff = new Schema({
name: String,
value: Number,
});
That works, but what if I want my stuff: array to be able to contain Stuff or OtherStuff....
var MyDocSchema = new Schema({
name: String,
stuff: [Stuff *or* OtherStuff ],
});
where Stuff is the same as before and OtherStuff is defined as
var OtherStuff = new Schema({
count: Number,
when: Date,
});
Types. ObjectId . A SchemaType is just a configuration object for Mongoose. An instance of the mongoose. ObjectId SchemaType doesn't actually create MongoDB ObjectIds, it is just a configuration for a path in a schema.
There are basically two ways to do this:
store Stuff and OtherStuff in another own collection (the same collection), and store only the id of the objects in the field, you can then populate the result. The trick with this solution is that you want to create two mongoose models pointing to the same collection.
Note: This solution is fine for big and vastly differing Stuff and OtherStuff objects (because of mongoDb storage heuristics), with a low Document count (because population is a slow process). Ultimately if the objects are very different they should have their own field though.
use discriminators. Basically you need three document Schemas for your example (other schemas stay the same):
// -- Stuff --
// Please copy from above
// -- OtherStuff --
// Please copy from above
// MyDocument -
var MyDocSchema = new Schema({ name: String });
// MyDocStuff -
var MyDocStuffSchema = new Schema({ stuff: [Stuff] });
// MyDocOtherStuff -
var MyDocOtherStuffSchema = new Schema({ stuff: [OtherStuff] });
var myDoc = new mongoose.Model( 'myDoc', myDocSchema );
var myDocStuff = myDoc.discriminator( 'myDocStuff', myDocStuffSchema );
var myDocOtherStuff = myDoc.discriminator( 'myDocOtherStuff', myDocOtherStuffSchema );
// when writing with this method, you need to know which model is relevant
// isOtherStuff() just checks for _when_ or _count_ fields
if( isOtherStuff(doc) ) {
myDocOtherStuff.create(doc);
} else {
myDocStuff.create(doc);
}
Note: this is the solution to use with polymorphic objects which look similar, that are fast for large N in doc.
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