cody cody - 3 months ago 13
Node.js Question

why doesn't mongoose save my model

I have this node.js code that saves an array of array of text into a MongoDB hosted at mongolab.com. I use Mongoose ORM and notice that the code connects to the database but the save method is not executed.

function save2Db(texts) {
var db = require('mongoose');
db.Promise = global.Promise;
db.connect('mongodb://user:pswd@ds013456.mlab.com:13456/heroku_xxxxxxx');
db.connection.on('error', console.error.bind(console, 'connection error!'));
db.connection.on('close', console.error.bind(console, 'closed db!'));
db.connection.once('open', function() {
console.log('opened db!');

/* Create schema */
var textSchema = new db.Schema({
date: { type: Date, default: Date.now },
text: [String]
});

/* Create model */
var TextModel = db.model('Text', textSchema, 'testCollection');

/* Save data to database */
texts.forEach(function(content) {

console.log(`saving ${content}`);

var t = new TextModel({text : content});

t.save(function (err) {
console.log('inside t.save');
if (err) {
console.error(err);
} else {
console.log('Saved to db');
}
}); //t.save
}); // texts.forEach

db.connection.close();
});
}

save2Db([['a','b'],['c'],['d','e','f','g']])


And get the output

opened db!
saving a,b
saving c
saving d,e,f,g
closed db!


Do you know why the save method does not work? Thank you.

Answer

t.save is a asynchron function. You are closing the connection of the database before the save could be run. If you want to close the db connection, you need to wait until all your save callbacks have been called. I would recommend using promises for that.

function save2Db(texts) {
    var db = require('mongoose');
    db.Promise = global.Promise;
    db.connect('mongodb://user:pswd@ds013456.mlab.com:13456/heroku_xxxxxxx');
    db.connection.on('error', console.error.bind(console, 'connection error!'));
    db.connection.on('close', console.error.bind(console, 'closed db!'));
    db.connection.once('open', function() {
        console.log('opened db!');

        /* Create schema */
        var textSchema = new db.Schema({
            date: {
                type: Date,
                default: Date.now
            },
            text: [String]
        });

        /* Create model */
        var TextModel = db.model('Text', textSchema, 'testCollection');

        /* Save data to database */
        var saves = [];
        texts.forEach(function(content) {

            console.log(`saving ${content}`);

            var t = new TextModel({
                text: content
            });
            saves.push(t.save());
        });
        Promise.all(saves)
            .then(() => db.connection.close())
            .catch(err => {
              console.log(err);
              db.connection.close();
            });
    });
}

Some additional notes: You should move your database initiation part out of your save2Db function as it would be called every time you want to save something. You also don't have to wait until the connection is opened as your mongoose model will do this anyway. Last but not least: you don't need to connect and close the database connection if you are doing db calls all the time. Just connect once and leave it open.