Mongoose保存子文档数组

时间:2015-07-05 23:47:11

标签: javascript node.js mongodb express mongoose

我正在努力尝试保存子文档数组。只是不会保存:

前端发送一个具有标题数组的Day对象,每个标题可以有一个内容数组(这是一个mongoose模式)。

var DaySchema = mongoose.Schema({
date: Date,
startTime: Date,
endTime: Date,
title: String,
order: Number,
description: String,
cohort: {
    type: objId,
    ref: 'cohort'
},
instructors: [{
    type: objId,
    ref: 'instructor'
}],
headings: [{
    title: String,
    subTitle: String,
    content: [{
        type:objId,
        ref: 'content'
    }]
}]
});


var ContentSchema = mongoose.Schema({
title: String,
description: String,
contentUrl: String,
dueDate: Date,
dateAssigned: Date,
downloadUrl: String
});

这是我用于PUT和POST一天的代码及其关联的Content对象。除了保存内容外,一切都有效。当我查看mongo shell时,标题下的每个内容字段都是这样的:

content: []

有什么想法吗?

exports.putdaycontent = function (req, res) {

var dayId = req.params.dayId;
var headings = req.body.headings;
var day = req.body;

var updateDay = function () {
    Day.update({_id: dayId}, day, {new: true, upsert: true}, function (err, day) {
        if (err)
            error.databaseError(req, res, err);

        res.send(day);
    });
};

if (headings) {
    for (var x = 0; x < headings.length; x++) {
        var h = headings[x];

        if (h.content) {
            for (var y = 0; y < h.content.length; y++) {
                var c = h.content[y];

                //If existing content update it
                if (c._id && c._id.length > 0) {
                    Content.update({_id: c._id}, c, {new: true,upsert: true}, function (err, content) {

                    });
                } else {
                    var content = new Content(c);
                    h.content[y] = content;
                }

            }
        }
    }
    day.headings = headings;
    updateDay();

} else {
    updateDay();
}


};

exports.postdaycontent = function (req, res) {

var headings = req.body.headings;
var day = req.body;
var cohortId = day.cohort._id;

var postDay = function () {
    var d = new Day(day);
    console.log("CONTENT DAYS:",d);
    d.save(function(err, newDay) {
       if (err)
           error.databaseError(req, res, err);

        Cohort.findOneAndUpdate({_id: cohortId}, {$push: {days: newDay}}, {upsert: true}, function(err, newCohort) {
            res.send({msg:"Successfully saved day to cohort"});
        });
    });
};

if (headings) {
    for (var x = 0; x < headings.length; x++) {
        var h = headings[x];

        if (h.content) {
            for (var y = 0; y < h.content.length; y++) {
                var c = h.content[y];

                var content = new Content(c);
                h.content[y] = content;
                console.log("CONTENT:",content);

            }
        }
    }
    day.headings = headings;
} 

postDay();
};

2 个答案:

答案 0 :(得分:2)

这是几天前我在2015年6月22日遇到的情况。这是我在github https://github.com/Automattic/mongoose/issues/3093上提出的问题的链接。

<小时/> 现在有两种解决方案可以解决您的问题。

  1. use .set() explicitly whenever you're modifying an array index
  2. 例如:

    doc.someArray.set('3', 'changed');
    doc.save();
    

    此处名为someArray的数组正在更改,因此我们需要使用array.set方法更改它。

    <强>缺点: 数组的每个元素都需要使用array.set()进行设置,例如,数组中的5个元素会更改,您需要使用array.set设置所有元素。

    <小时/> 2.将数组标记为已修改,然后保存。

    例如:

    doc.array[3] = 'changed';
    doc.markModified('array');
    

    这是另一种方法,当您无法显式调用array.set方法时。例如:在我的情况下,我使用loadash来合并文档并保存它,我无法使用array.set,因此我使用了array.markModified

    Benifit: 您不需要将数组中的每个元素设置为上面的array.set方法。

    缺点:

    如果是每个阵列,您需要在保存之前将其标记为已修改。  例如:如果文档中有10个数组,则需要在保存之前将它们全部标记为已修改:例如,

     doc.markModified('array1');
     doc.markModified('array2');
     doc.markModified('array3');
    

    <小时/> mongoose中仍然没有选项将多个数组标记为已修改。我已在上面分享的链接中请求了此功能。

    这就像是:

    profile.markAllModified(['arrayFirst','arraySecond','arrayThird','arrayFourth']);
    

    已被添加到mongoose的里程碑4.0.7,希望我们很快就会看到这个功能。

答案 1 :(得分:0)

所以我假设Mongoose会保存子文档,只要他们有_id字段 - 但显然不是。保存子文档数组的解决方案是

  1. 从json
  2. 为数组中的每个子文档创建一个新的Model对象
  3. 在每个对象上调用save()
  4. 父对象不关心子文档的_id是否存在 - 它甚至可以在我将子文档本身保存在数据库中之前存储它。
  5. 此修复程序只是在子文档上调用.save()。

    var content = new Content(c); content.save(); h.content[y] = content;

    exports.putdaycontent = function(req,res){

    var dayId = req.params.dayId;
    var headings = req.body.headings;
    var day = req.body;
    
    var updateDay = function () {
        Day.update({
            _id: dayId
        }, day, {
            new: true,
            upsert: true
        }, function (err, day) {
            if (err)
                error.databaseError(req, res, err);
    
            res.send(day);
        });
    };
    
    if (headings) {
        for (var x = 0; x < headings.length; x++) {
            var h = headings[x];
    
            if (h.content) {
                for (var y = 0; y < h.content.length; y++) {
                    var c = h.content[y];
    
                    //If existing content update it
                    if (c._id && c._id.length > 0) {
                        Content.update({
                            _id: c._id
                        }, c, {
                            new: true,
                            upsert: true
                        }, function (err, content) {
    
                        });
                    } else {
                        var content = new Content(c);
                        content.save();
                        h.content[y] = content;
                    }
    
                }
            }
        }
        day.headings = headings;
        updateDay();
    
    } else {
        updateDay();
    }
    
    
     };