I tried this with the built-in mongoose inheritance functions (and not with the plugin extension), but still haven't had much luck. This is a simplified code example that I am trying to use that shows the same problem. This is based on the extended mongoose documentation for schema inheritance using discriminators - http://mongoosejs.com/docs/api.html#model_Model.discriminator
var util = require('util'); var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/problem'); var Schema = mongoose.Schema; var ObjectId = Schema.ObjectId; function BaseSchema() { Schema.apply(this, arguments); this.add({ name: String, createdAt: Date }); } util.inherits(BaseSchema, Schema); var BossStatusSchema = new Schema({ status: String }); var BossStatus = mongoose.model('BossStatus', BossStatusSchema); var PersonSchema = new BaseSchema(); var Person = mongoose.model('Person', PersonSchema); var BossSchema = new BaseSchema({ department: String, bossStatus: { type: ObjectId, ref: 'BossStatus' } }); var Boss = Person.discriminator('Boss', BossSchema);
Example code for adding documents:
var superBoss = new BossStatus({ status: 'super' }); var normalBoss = new BossStatus({ status: 'normal' }); var andy = new Person({ name: 'Andy' }); var billy = new Boss({ name: 'Billy', bossStatus: superBoss._id }); var callback = function(err, result) { console.dir(err); console.dir(result); }; superBoss.save(callback); normalBoss.save(callback); andy.save(callback); billy.save(callback);
So, if you find a record without :
Person .findOne({ name: 'Billy' }) .exec(callback);
The result will be as expected, bossStatus refers to the _id from the bossstatuses collection:
null { name: 'Billy', bossStatus: 52a20ab0185a7f4530000001, _id: 52a20ab0185a7f4530000004, __v: 0, __t: 'Boss' }
When adding a call:
Person .findOne({ name: 'Billy' }) .populate('bossStatus') .exec(callback);
The resulting bossStatus property of Person null :
null { name: 'Billy', bossStatus: null, _id: 52a20ab0185a7f4530000004, __v: 0, __t: 'Boss' }
EDIT:
Well, I just compiled what is probably the best example of what I'm trying to achieve, the schema structure is more suitable for a relational database, but hopefully makes the problem more clear.
var util = require('util'); var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/problem'); var Schema = mongoose.Schema; var ObjectId = Schema.ObjectId; function BaseSchema() { Schema.apply(this, arguments); this.add({ name: { type: String, unique: true, required: true } }); } util.inherits(BaseSchema, Schema); var DeviceSchema = new BaseSchema(); var LocalDeviceSchema = new BaseSchema({ driver: { type: ObjectId, ref: 'Driver' } }); var RemoteDeviceSchema = new BaseSchema({ networkAddress: { type: ObjectId, ref: 'NetworkAddress' } }); var DriverSchema = new Schema({ name: { type: String, unique: true, required: true } }); var NetworkHostSchema = new Schema({ host: { type: String, unique: true, required: true } }); var NetworkAddressSchema = new Schema({ networkHost: { type: ObjectId, ref: 'NetworkHost' }, port: { type: Number, min: 1, max: 65535 } }); var Driver = mongoose.model('Driver', DriverSchema); var NetworkHost = mongoose.model('NetworkHost', NetworkHostSchema); var NetworkAddress = mongoose.model('NetworkAddress', NetworkAddressSchema); var Device = mongoose.model('Device', DeviceSchema); var LocalDevice = Device.discriminator('LocalDevice', LocalDeviceSchema); var RemoteDevice = Device.discriminator('RemoteDevice', RemoteDeviceSchema); var networkHost = new NetworkHost({ host: '192.168.2.1' }); var networkAddress = new NetworkAddress({ networkHost: networkHost._id, port: 3000 }); var remoteDevice = new RemoteDevice({ name: 'myRemoteDevice', networkAddress: networkAddress._id }); var driver = new Driver({ name: 'ftdi' }); var localDevice = new LocalDevice({ name: 'myLocalDevice', driver: driver._id }); var callback = function(err, result) { if(err) { console.log(err); } console.dir(result); }; var deviceCallback = function(err, device) { if(err) { console.log(err); } switch(device.__t) { case 'LocalDevice': console.log('Would create a local device instance passing populated result'); break; case 'RemoteDevice': console.log('Would create a remote device instance passing populated result'); break; } }; Device .findOne({name: 'myLocalDevice'}) .populate('driver') .exec(deviceCallback);
LocalDevice and RemoteDevice schemes can (and probably will) include other differences. A switch, for example, would use DeviceFactory or something to create instances. My thinking was that I would have to look for the device table for the device by name and fill out the collection links (if this is the correct terminology?) Without having to specify the collection to search for - was this my understanding of the circuit's inheritance point - or did I completely not understand?
Thanks for the answers so far!