无法重置sailsjs中的模型实例属性

时间:2015-06-07 16:35:42

标签: sails.js

在开始之前:我已经使用种子数据和两个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没有运气。

3 个答案:

答案 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个实例,然后映射他们之后进入程序,节省了大量的查询。