Lucas Watson Lucas Watson - 1 year ago 116
AngularJS Question

Mongoose doesn't create subdocument from JSON array

I'm trying to write a JSON object that contains both first-level data along with arrays into MongoDB.

What happens instead is all first-level data is stored, but anything contained in an array isn't. When logging the data the server receives, I see the entire object, which leads me to believe there's something wrong with my Mongoose code.

So for example if I send something like this:

issueId: "test1",
issueTitle: "testtest",
rows: [
{order:1,data: [object]},
{order:2,data: [object]},

Only the following gets stored:

issueId: "test1",
issueTitle: "testtest",
lastUpdated: Date,

I have the following model for Mongo:

var mongoose = require('mongoose');

var model = mongoose.Schema({

issueId : String,
issueTitle : String,
lastUpdated : {type: Date, default :},

rows : [{
order : Number,
data : [
title : String,
text : String,
link : String,


module.exports = mongoose.model('Model', model);

And the routing code, where I believe the problem likely is:

const mongoose = require('mongoose');
const Model = require('./model.js');
...'/api/data/update', function(req, res) {
let theData = req.body.dataToInsert;


{issueId : theData.issueId},
{upsert: true},
if(err) throw err;

As well, here's the part of the Angular controller storing the data. I don't think there's any problem here.

pushToServer = function() {
dataToInsert : $scope.dataObject,
}).then(function successCallback(res){
console.log("all good", JSON.stringify(res,null,3));
}, function errorCallback(res){
console.log("arg" + res);

Answer Source

Look at the first question in the mongoose FAQ:

Mongoose doesn't create getters/setters for array indexes; without them mongoose never gets notified of the change and so doesn't know to persist the new value. The work-around is to use MongooseArray#set available in Mongoose >= 3.2.0.

// query the document you want to update
// set the individual indexes you want to update
// save the document
doc.array.set(3, 'changed');;


I think this would work to update all of the rows. I'd be interested to know if it does work.

let rowQueries = [];
theData.rows.forEach(row => {
    let query = Model.findOneAndUpdate({
        issueId: theData.issueId,
        'row._id': row._id
    }, {
        $set: {
            'row.$': row

Promise.all(rowQueries).then(updatedDocs => {
    // updated