Mongoose保存子文档数组

Spe*_*tak 2 javascript mongoose mongodb node.js express

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

前端发送一个 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
});
Run Code Online (Sandbox Code Playgroud)

这是我用来 PUT 和 POST a Day 的代码及其关联的 Content 对象。除了保存内容之外,一切正常。当我查看 mongo shell 时,标题下的每个内容字段如下所示:

content: []
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

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();
};
Run Code Online (Sandbox Code Playgroud)

Nae*_*ikh 6

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


现在您的问题有两种解决方案。

  1. 每当修改数组索引时显式使用 .set()

例如:

doc.someArray.set('3', 'changed');
doc.save();
Run Code Online (Sandbox Code Playgroud)

这里指定的数组someArray正在被更改,因此我们需要使用 array.set 方法来更改它。

缺点:数组的每个元素都需要使用 设置array.set(),因此,例如,数组中的 5 个元素发生变化,您将需要使用 设置所有元素array.set


2. 将数组标记为已修改,然后保存。

例如:

doc.array[3] = 'changed';
doc.markModified('array');
Run Code Online (Sandbox Code Playgroud)

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

好处:您不需要像上面的array.set方法一样设置数组中的每个元素。

退税:

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

 doc.markModified('array1');
 doc.markModified('array2');
 doc.markModified('array3');
Run Code Online (Sandbox Code Playgroud)


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

所以那就是这样的:

profile.markAllModified(['arrayFirst','arraySecond','arrayThird','arrayFourth']);
Run Code Online (Sandbox Code Playgroud)

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