在开始之前:我已经使用种子数据和两个REST端点创建了一个非常小的git repo来测试此问题:https://github.com/juanpasolano/sails-nested-test
所以我有3个模型:Appointment
有许多procedure
,其中有一对一procedureItem
。
由于帆中没有嵌套的人口,因此使用procedures
手动procedureItem
使用以下内容:
Appointment.find(1).exec(function(err, appointments){
if(err) return res.negotiate(err);
async.eachSeries(appointments, function(appointment, cb){
Procedure.find({appointment: appointment.id}).populate('procedureItem').exec(function(errP, procedures){
if(errP) return cb(errP);
appointment.procedures = procedures;
appointment.proceduress = procedures;
cb()
})
}, function(errE){
if(errE) return cb(errE);
res.ok(appointments)
所以问题是当我想用新的数组程序替换procedures
属性时(我需要嵌套的深度)它只是没有设置,如果你点击了端点演示,没有procedures
属性可用。
作为测试,我将相同的新过程数组附加到proceduress
(double s)属性,并且这个属性设置正确。
我尝试过使用.toObject()
方法,但没有运气
尝试过风帆0.10.5和0.11.0没有运气。
答案 0 :(得分:1)
是的,没有过程属性,因为约会有多个过程,因此没有字段过程在 Appointment 表中的DB中。所以,如果你不填充像:
Appointment.find(1).populate('procedures').exec(function(err, appointments){
.....
}
约会对象
中没有属性程序答案 1 :(得分:1)
前一段时间我遇到了完全相同的问题,我相信这是因为"程序"属性正由模型使用而无法设置。我最终克隆每一行,然后可以设置值。
要更改代码:
if(err) return res.negotiate(err);
var toreturn=_.map(appointments, function(a){
var b=_.clone(a); // so you clone it to a new obj, then you can set the procedure...
b.procedures = 'aaaa'
return b;
})
//res.json(toreturn); // Here you will get appointments with procedures='aaa'
async.eachSeries(toreturn, function(appointment, cb){
Procedure.find({appointment: appointment.id}).populate('procedureItem').exec(function(errP, procedures){
if(errP) return cb(errP);
appointment.proceduress = procedures;
appointment.procedures = procedures;
cb()
})
}, function(errE){
if(errE) return cb(errE);
res.ok(toreturn)
})
我不知道为什么会发生这种情况,但这只是一个解决方案。
另外,我可以建议你不要为每个指定执行异步,每个指定需要查询,执行两个大查找,然后循环合并它们吗?
这样的事情:
var globalApps=[];
Appointment.find().then(function(apps){
globalApps=apps;
var appIDs=apps.map(function(a){return a.id}); //Get all appointment IDs
return Procedure.find({appointment:appIDs}).populate('procedureItem');
}).then(function(procs){ //This procs is all procedures match the ids
var toReturn =_.map(globalApps,function(a){
var b=_.clone(a);
b.procedure=_.find(procs,{appointment:b.id}); // This is O(n^2) complexity matching, but you can do something smart.
return b;
});
// Now you have toReturn as the appointment array.
return res.json(toReturn);
})
我之前在这个问题上花了很多时间,很高兴有人遇到同样的问题
答案 2 :(得分:1)
来自Balderdash的@ sgress454。您遇到的问题是procedures
属性不是普通的Javascript变量;它有一个“getter”和一个“setter”,这些是必要的,以便让它们起作用:
appointment.procedures.add(<some Procedure obj or id>);
appointment.procedures.remove(<some Procedure id>);
因为设置器,尝试将procedures
属性设置为新值将不起作用。克隆约会是一种可接受的解决方法(您可以执行appointment.toObject()
),因为它将这些特殊属性转换为普通的旧Javascript变量。但在您的情况下,您似乎实际上不需要替换procedures
数组 - 您只需要填写每个过程的procedureItem
。因为只有代表多对多关联的属性才有getter和setter,所以你可以完成这个,而不需要任何克隆:
Appointment
// Find the appointments
.find({...some criteria...})
// Populate each appointment's procedure
.populate('procedure')
.exec(function(err, appointments) {
if (err) {return res.negotiate(err);}
// Loop through the returned appointments
async.each(appointments, function(appointment, appointmentCb) {
// For each one, loop through its procedures
async.each(appointment.procedures, function(procedure, procedureCb) {
// Look up the related procedureItem
ProcedureItem.findOne(procedure.procedureItem).exec(function(err, procedureItem) {
if (err) {return procedureCb(err);}
// Attach the procedureItem object to the procedure
procedure.procedureItem = procedureItem;
return procedureCb();
});
}, appointmentCb);
}, function done(err) {
if (err) {return res.negotiate(err);}
res.ok(appointments);
});
});
请注意,这里可以进行大量优化 - 您可以在检索约会后拔出所有ProcedureItem
ID,一次查找所有ProcedureItem
个实例,然后映射他们之后进入程序,节省了大量的查询。