Javascript 单个模式数组中的多个模式引用-mongoose

Javascript 单个模式数组中的多个模式引用-mongoose,javascript,mongodb,mongoose,mongoose-populate,Javascript,Mongodb,Mongoose,Mongoose Populate,能否在mongoose模式中填充一个数组,并引用几个不同的模式选项 为了稍微澄清这个问题,假设我有以下模式: var scenarioSchema = Schema({ _id : Number, name : String, guns : [] }); var ak47 = Schema({ _id : Number //Bunch of AK specific parameters }); var m16 = Schema({ _id

能否在mongoose模式中填充一个数组,并引用几个不同的模式选项

为了稍微澄清这个问题,假设我有以下模式:

var scenarioSchema = Schema({
  _id     : Number,
  name    : String,
  guns : []
});

var ak47 = Schema({
  _id     : Number
  //Bunch of AK specific parameters
});

var m16 = Schema({
  _id     : Number
  //Bunch of M16 specific parameters
});
我可以用一堆ak47m16填充枪阵列吗?我可以将两个放在同一个枪阵列中吗?或者它是否需要资产数组中的populate ref,比如这样,它将其限制为单个特定类型

guns: [{ type: Schema.Types.ObjectId, ref: 'm16' }]
我知道我可以为不同的枪类型使用单独的数组,但随着项目的扩展,这将在模式中创建大量额外字段,其中大部分字段将根据加载的场景保留为空

var scenarioSchema = Schema({
  _id     : Number,
  name    : String,
  ak47s : [{ type: Schema.Types.ObjectId, ref: 'ak47' }],
  m16s: [{ type: Schema.Types.ObjectId, ref: 'm16' }]
});

那么回到问题上来,我可以在一个数组中粘贴多个模式引用吗?

您在这里寻找的是mongoose方法。这基本上允许您在同一集合中存储不同类型的对象,但将它们作为可区分的第一类对象

请注意,此处的“相同集合”原则对于
.populate()
的工作方式以及包含模型中引用的定义非常重要。既然你真的只能指向“一个”模型作为参考,但是还有一些其他的魔法可以让一个模型看起来一样多

示例列表:

var util=require('util'),
async=require('async'),
mongoose=require('mongoose'),
Schema=mongoose.Schema;
猫鼬mongodb://localhost/gunshow');
//mongoose.set(“调试”,true);
var scenarioSchema=新架构({
“name”:字符串,
“guns”:[{“type”:Schema.Types.ObjectId,“ref”:“Gun”}]
});
函数BaseSchema(){
Schema.apply(这个,参数);
//普通枪械
这个。添加({
“createdAt”:{“type”:Date,“default”:Date.now}
});
}
继承(BaseSchema,Schema);
var gunSchema=new BaseSchema();
var ak47Schema=新的BaseSchema({
//Ak74材料
});
ak47Schema.methods.shoot=函数(){
返回“裂纹!裂纹”;
};
var m16Schema=新的BaseSchema({
//M16材料
});
m16Schema.methods.shoot=函数(){
return“bum!!”
};
var Scenario=mongoose.model(“Scenario”,scenarioSchema);
var Gun=mongoose.model(“Gun”,gunSchema);
var Ak47=枪鉴别器(“Ak47”,ak47Schema);
var M16=枪鉴别器(“M16”,m16Schema);
异步系列(
[
//清理
函数(回调){
async.each([Scenario,Gun],函数(model,callback){
删除({},回调);
},回调);
},
//添加一些枪并添加到场景中
函数(回调){
异步瀑布(
[
函数(回调){
map([Ak47,M16],函数(gun,回调){
gun.create({},回调);
},回调);
},
函数(枪、回调){
Scenario.create({
“名称”:“测试”,
“枪”:枪
},回调);
}
],
回拨
);
},
//填充场景
函数(回调){
Scenario.findOne().populate(“guns”).exec(函数(err,数据){
log(“填充:\n%s”,JSON.stringify(数据,未定义,2));
//为了好玩,开枪吧!
数据。枪。forEach(功能(枪){
console.log(“%s表示%s”,gun.\u t,gun.shoot());
});
回调(err);
});
},
//展示枪支收藏
函数(回调){
Gun.find().exec(函数(err,guns){
log(“Guns:\n%s”,JSON.stringify(Guns,未定义,2));
回调(err);
});
},
//显示魔法过滤
函数(回调){
Ak47.find().exec(函数(err,Ak47){
log(“Magic!:\n%s”,JSON.stringify(ak47,未定义,2));
回调(err);
});
}
],
功能(err){
如果(错误)抛出错误;
mongoose.disconnect();
}
);
和输出

填充:
{
“_id”:“56c508069d16fab84ead921d”,
“名称”:“测试”,
“_v”:0,
“枪支”:[
{
“_id”:“56c508069d16fab84ead921b”,
“_v”:0,
“u_t”:“Ak47”,
“创建数据”:“2016-02-17T23:53:42.853Z”
},
{
“_id”:“56c508069d16fab84ead921c”,
“_v”:0,
“u_t”:“M16”,
“创建数据”:“2016-02-17T23:53:42.862Z”
}
]
}
Ak47说快说!裂纹
M16上写着“怪”!!
枪支:
[
{
“_id”:“56c508069d16fab84ead921b”,
“_v”:0,
“u_t”:“Ak47”,
“创建数据”:“2016-02-17T23:53:42.853Z”
},
{
“_id”:“56c508069d16fab84ead921c”,
“_v”:0,
“u_t”:“M16”,
“创建数据”:“2016-02-17T23:53:42.862Z”
}
]
魔法!:
[
{
“_id”:“56c508069d16fab84ead921b”,
“_v”:0,
“u_t”:“Ak47”,
“创建数据”:“2016-02-17T23:53:42.853Z”
}
]
您还可以取消注释清单中的
mongoose.set(“debug”,true)
行,以查看mongoose实际上是如何构造调用的

因此,这表明您可以将不同的模式应用于不同的第一类对象,甚至可以像实际对象一样附加不同的方法。Mongoose将所有这些存储在带有附加模型的“guns”集合中,它将包含鉴别器引用的所有“类型”:

var Gun=mongoose.model(“Gun”,gunSchema);
var Ak47=枪鉴别器(“Ak47”,ak47Schema);
var M16=枪鉴别器(“M16”,m16Schema);
但是,每一种不同的“类型”都以一种特殊的方式用它自己的模型引用。因此您可以看到,当mongoose存储和读取对象时,有一个特殊的
\uu t
字段,告诉它要应用哪个“模型”,并因此附加了模式

例如,我们称之为
.shoot()
方法,每个模型/模式的定义都不同。而且您仍然可以将每一个单独用作查询或其他操作的模型,因为
Ak47
将在所有查询/升级中自动应用
\t

因此,虽然存储在一个集合中,但它可以看起来是多个集合,但也有保留这些集合的好处