【发布时间】:2013-12-24 04:37:56
【问题描述】:
我一直在尝试使用 mongoose 的内置继承功能(而不是扩展插件),但到目前为止运气不佳。这是我尝试使用的代码的简化示例,它表现出相同的问题。这是基于 mongoose 文档的扩展版本,用于使用鉴别器进行模式继承 - 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);
添加文档的示例代码:
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);
所以当找到记录时没有填充:
Person
.findOne({
name: 'Billy'
})
.exec(callback);
结果如预期,bossStatus引用了bossstatuses集合中的一个_id:
null
{ name: 'Billy',
bossStatus: 52a20ab0185a7f4530000001,
_id: 52a20ab0185a7f4530000004,
__v: 0,
__t: 'Boss' }
添加填充调用时:
Person
.findOne({
name: 'Billy'
})
.populate('bossStatus')
.exec(callback);
Person 结果的结果 bossStatus 属性为 null:
null
{ name: 'Billy',
bossStatus: null,
_id: 52a20ab0185a7f4530000004,
__v: 0,
__t: 'Boss' }
编辑:
好的,我刚刚整理了一个可能是我正在尝试实现的更好示例的示例,架构结构更适合关系数据库,但希望使问题更清晰。
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);
};
/*
// Uncomment to save documents
networkHost.save(function() {
networkAddress.save(function() {
remoteDevice.save(callback);
});
});
driver.save(function() {
localDevice.save(callback);
});
*/
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 和 RemoteDevice 架构可能(并且可能会)包含其他差异。 例如,开关将使用 DeviceFactory 或其他东西来创建实例。我的想法是应该可以通过“名称”在设备表中搜索设备并填充集合引用(如果这是正确的术语?)而不必指定要搜索的集合 - 这是我对这一点的理解模式继承 - 还是我完全误解了?
感谢到目前为止的回复!
【问题讨论】:
-
这些答案是否解决了您的问题?您找到其他解决方案了吗?
-
不幸的是他们没有解决这个问题,这似乎仍然是猫鼬的一个缺点——也许它会在未来的版本中得到解决。我还没有找到其他解决方案,但从那以后就没有真正研究过。
标签: node.js inheritance mongoose populate