Juan Acevedo
Juan Acevedo

Reputation: 1788

mongoose save function not working. post('save') not getting called but no error

I'm pretty new to web development and coming from a java/android background. I read all other so questions regarding mongoose save() not saving to db but still can't get this to write into the db.

Thank you!

I wrote grocery.js which defines my schema and I wrote another script groceryQueries.js to write and read into the database. The save prehook is called, however the save posthook isn't. This is the command I use:

node groceryQueries.js insert fruits,apple,appl.jpg,.46

Here is the output:

(node:14548) DeprecationWarning: open() is deprecated in mongoose >= 4.11.0, use openUri() instead, or set the useMongoClient option if using connect() or createConnection(). See http://mongoosejs.com/docs/connections.html#use-mongo-client

connected to mongodb

params: fruits,apple,appl.jpg,.46 (node:14548) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

saving apple

grocery.js:

var mongoose = require('mongoose');

var grocerySchema = new mongoose.Schema({
    name: {
        type: String,
        unique: false,
        required: true,
        trim: true
    },
    img: {
        type: String,
        unique: false,
        required: false,
        trim: true
    },
    price: {
        type: Number,
        unique: false,
        required: true,
        trim: true
    },
    category: {
        type: String,
        unique: false,
        required: true,
        trim: true
    }
});

grocerySchema.pre('save',function(next) {
    var grocery = this;
    console.log("saving "+grocery.name);
    next();
});
grocerySchema.post('save',function(next) {
    console.log("post saving ");
    next();
});

grocerySchema.statics.COLLECTION_NAME = function() {
    return 'groceries';
}

grocerySchema.methods.toString = function() {
    console.log(Grocery.COLLECTION_NAME() + ", Category: " + this.category + " is " + this.name+" and costs "+this.price+"");
};

var Grocery = mongoose.model('groceries',grocerySchema);
module.exports = Grocery;

groceryQueries.js:

var mongoose = require('mongoose');
var url = "mongodb://localhost:27017/deliveryservice";
mongoose.connect(url);
const Grocery = require('../server/models/grocery');

var db = mongoose.connection;
db.on('error',console.error.bind(console,'connection error'));
db.once('open',function() {
    console.log("connected to mongodb");
    doQueries();
});

function doQueries() {
var groceryCollection = Grocery.COLLECTION_NAME();//"groceries";
var arg = process.argv[2];

if (arg == 'find' ||
    arg == 'insert') {
        if (arg == 'find') {
            var nameArg = process.argv[3];
            if (nameArg === undefined) {
                var error = new Error('undefined name');
                throw error;
            }
            Grocery.find({name: nameArg},function(err,groceries) {
                if (err) {
                    return console.error(err);
                }
                console.log("groceries: " + groceries);
                db.close();
            });
        } else if (arg == 'insert') {
            var paramsArg = process.argv[3];
            var throwError = false;
            if (paramsArg === undefined) {
                throwError = true;
            }
            console.log("params: "+paramsArg);
            var parameters = paramsArg.split(",");
            if (parameters.length != 4) {
                throwError = true;
            }
            if (throwError) {
                var error = new Error('undefined parameters <name>,<img>,<price>');
                throw error;
            }
            var newGrocery = new Grocery({category: parameters[0],name: parameters[1], img: parameters[2], price: parameters[3]});
            //console.log("before save: "+newGrocery.toString());
            newGrocery.save(function(err,newGrocery) {
                if (err) {
                    throw err;
                }
                grocery.toString();
            });
            db.close();
        }
} else {
    console.log('help: find <name> | insert <category>,<name>,<img>,<price>')
}
}

Upvotes: 0

Views: 1600

Answers (2)

Kevin Pe&#241;a
Kevin Pe&#241;a

Reputation: 772

The main problem in your code is that you are closing the connection to the db before the saving occurs. Note that all db operations in mongoose are asynchronous and calling an asynchronous function just schedules the operation for the next tick of the event loop.

You want to do this instead:

newGrocery.save(function(err, newGrocery) {
  if (err) {
    throw err;
  }
  // grocery.toString(); <- typo here btw, param is called newGrocery
}).then(function() {
  db.close();
});

And delete next from your post-save hook, that parameter is actually the saved grocery and you should not call it like a function.

grocerySchema.post('save', function() {
  console.log('post saving ');
})

Bonus

To get rid of the warning about open() and connect() being deprecated use this to opt-in to the new connection logic:

mongoose.connect(url, {
  useMongoClient: true,
});

To get rid of the warning about promises add this after requiring mongoose:

// Use native promises
mongoose.Promise = global.Promise

Upvotes: 0

lysium
lysium

Reputation: 331

save returns a promise, which you have to wait for:

        newGrocery.save(function(err,newGrocery) {
            if (err) {
              console.log(err);
                throw err;
            }
            newGrocery.toString();  // you had a typo here btw
        }).then(function() { db.close();});

Your code runs db.close() before mongoose had a chance to save anything.

Upvotes: 1

Related Questions