admin管理员组文章数量:1356815
I'm struggling trying to save a subdocument array. Just wont save:
The front end sends up a Day object that has an array of headings, and each heading can have a content array (which is a mongoose schema).
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
});
This is the code I'm using to PUT and POST a Day, with its associated Content objects. Everything works except for saving the content. When I look in the mongo shell each content field under headings looks like this:
content: []
Any thoughts?
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();
};
I'm struggling trying to save a subdocument array. Just wont save:
The front end sends up a Day object that has an array of headings, and each heading can have a content array (which is a mongoose schema).
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
});
This is the code I'm using to PUT and POST a Day, with its associated Content objects. Everything works except for saving the content. When I look in the mongo shell each content field under headings looks like this:
content: []
Any thoughts?
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();
};
Share
Improve this question
asked Jul 5, 2015 at 23:47
SpentakSpentak
3,3594 gold badges22 silver badges31 bronze badges
2
-
Asynchronous functions and synchronous loops don't mix well. You should never use
.update()
without$set
or similar operators. All arrays are referenced so unless the actual objects exist already in another collection you don't create this way. HopefullyobjId
has been imported fromSchema.Types.ObjectId
. Those are just a few thoughts that e to mind at first glance. – Blakes Seven Commented Jul 5, 2015 at 23:58 - I'm not sure what you are saying I should do. The idea is a user creates a Day with X amount of headings and X amount of content objects within the content array. Then they click save and the back-end updates objects that need to be updated, and if it doesn't exist it creates it. I could save each Content object individually, but how would I make sure they are added to the array in the Content array inside the Day? – Spentak Commented Jul 6, 2015 at 0:09
2 Answers
Reset to default 6This is something i faced a few days ago on 22nd june 2015. here is the link to the issue i raised on github https://github./Automattic/mongoose/issues/3093.
Now there are two solutions to your problem.
- use .set() explicitly whenever you're modifying an array index
for example:
doc.someArray.set('3', 'changed');
doc.save();
here the array named someArray
is being changed and thus we need to change it using array.set method.
Drawback:
each single elementy of the array need to be set using array.set()
, so for example, 5 elements inside array change you will need to set all of them using array.set
.
2. Mark the array as modified and then save it.
for example:
doc.array[3] = 'changed';
doc.markModified('array');
This is another way, when you can not explicitly call the array.set
method. for example: in my case i used loadash to merge the document and saved it, there was no way i could use array.set
, thus i used array.markModified
.
Benifit:
You will not need to set each of your element inside array as the above array.set
method.
Drawback:
In case of each array you will ned to mark it as modified before saving. for example: if you have 10 arrays in your document, you will need to mark them all as modified before saving: like,
doc.markModified('array1');
doc.markModified('array2');
doc.markModified('array3');
There is still no option in mongoose to mark multiple arrays as modified. I have requested this feature in the link i have shared above.
So that would be something like:
profile.markAllModified(['arrayFirst','arraySecond','arrayThird','arrayFourth']);
which has been added to milestone 4.0.7 of mongoose, hope we see this feature soon.
So I had assumed that Mongoose would save sub documents so long as they had the _id field - but apparently not. The solution to saving sub-document arrays is to
- Create a new Model object for each sub-document in the array from the json
- Call save() on each object
- The parent object doesn't care if the _id of the sub-document exists or not - it can just store it before I even save the sub-document itself in the database.
Again the fix was just calling .save() on the sub-document.
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();
}
};
本文标签: javascriptMongoose save subdocument arrayStack Overflow
版权声明:本文标题:javascript - Mongoose save subdocument array - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744071666a2586000.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论