Mongoose instance .save() not working
Asked Answered
F

11

36

I have a problem with Mongoose and MongoDb

It is very interesting that only Model.update works and save never works and does not even fire callback.

Mongoose: 4.4.5 MongoDB: 3.0.8

Express Route

var mongoose = require('mongoose');
mongoose.connect("mongodb://127.0.0.1:27017/db");
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function(callback) {
    console.log("connection to db open")
});
var User = require("../models/user.js");

User Model

var user = new Schema({
    uid: { type: Number, required: true, unique: true},
    hwid: { type: String, default:""},
    bol:{type:String,default:""}
});

Update Enpoint

Working version: Model.update()

User.update({_id: id}, {
    uid: 5, 
}, function(err, numberAffected, rawResponse) {
    console.log(err);
})

Not working version and I have to solve this: Object.save()

User.find({_id:id}, function(err,user){
    if(err){
         console.log(err);
    }
    if(!user){
         console.log("No user");
    }else{
        user.uid = 5;
        user.save(function(err,news){
            console.log("Tried to save...");
        });
    }
    console.log("At least worked");
})

Even callback is not firing. Connection successfully opens. It never invokes callback.


  1. Tried to use var User = connection.model('User', schema) didn't work.
Footer answered 1/3, 2016 at 21:14 Comment(8)
I know that your comment says it's a mongo object, but honestly there's nothing in what you've shown to prove that, and it's the most likely reason your .save method is not firing. How are you verifying that it's the actual instance returned from the DB?Bilbao
@Bilbao Updated question for youReam
what happens when you console.log user inside of the .find() callback ?Adjudge
@JesseKernaghan Nothing, it is not invoking callback.Ream
@JesseKernaghan,@Bilbao Thank you for helping, fixed the problem by myself. Made a newby mistake.Ream
@AhmetCanGüven, can you post a regular answer to your question? This will help to not generate unneeded late answersHuston
@Huston Thank you for the suggestion. Do you suggest that I should combine possible cases into a single answer?Ream
@AhmetCanGüven sorry, I didn't realize you had already replied, and marked your answer as accepted! I just read your previous comment, " fixed the problem by myself" etc. My bad :)Huston
F
32

I am not going to delete this question because people may encounter this problem too. Actually problem was not related with MongoDb or Mongoose. When you call Object.save() responsibility chain is like below:

  1. Schema.pre("save")
  2. Save data to dabe
  3. Schema.post("save")

So if you block pre("save") and don't call next() handler you won't be able to save your document. This was my case, I forgot the next() call inside an if statement and tried to find the error for more than 3 hours.

user.pre("save", function(next) {
    if(!this.trial){
        //do your job here
        next();
    }
}

When this.trial == true, next handler won't be reachable.

To prevent errors like this we should take care of branch coverage, reporters can show us untested codes. Your problem might be related with this too. Be sure you are calling next() if your document should be saved.

Fixed Version

user.pre("save", function(next) {
    if(!this.trial){
        //do your job here
    }
    next();
}
Footer answered 1/3, 2016 at 22:13 Comment(2)
Can we be realistic here and note that since your question itself makes no mention of a "pre save hook" then this is not really a solution that anyone was going to arrive at. Yes of course if the middleware continuation was not called then the code is just going to get stuck and not continue. And these are actually "callbacks" and not promises.Cremate
Thanks for saving my sanity... this very same thing happened and I've wasted like 3 hours trying to figure out WTH was going on...Selmaselman
M
120

I have the same problem. my problem was about changing an array inside db, then when I try to use .save(), it didn't understand that I changed any thing, then the .save() didn't work. I just use markModified() before use .save() and my problem become solved.

this is my code with problem: (not working)

club.members[index].name = new_name;
club.save();

this is my solved code: (working)

club.members[index].name = new_name;
club.markModified('members');
club.save();

enjoy!

Maeda answered 18/4, 2019 at 4:35 Comment(9)
My problem was similar, the changes were not explicit enough. Do not try to get clever like this: document.keys = { ...document.keys, ...updates } Instead apply all the changes one by oneNobility
Wow, this is super helpful! I was using a mutator function to modify the contents of an array, and Mongoose wasn't picking them up. This answer ended a multi-hour bug hunt.Nursling
Just a side note, it works with lists too if you have a complex update like me ( :Reactive
Also fixed my issues when updating some nested property in a MapDoriandoric
This worked for me. Thank you very much! Works with objects too. Not just array.Aldos
@AllJs Is there anyway to report this to the guys who maintain mongoose?Gerthagerti
Thank you very much from the future!Zohara
Thanks a bunch :)Eugeniusz
There are so many unobvious things in mongodb causing everyone to waste their time!Daren
F
32

I am not going to delete this question because people may encounter this problem too. Actually problem was not related with MongoDb or Mongoose. When you call Object.save() responsibility chain is like below:

  1. Schema.pre("save")
  2. Save data to dabe
  3. Schema.post("save")

So if you block pre("save") and don't call next() handler you won't be able to save your document. This was my case, I forgot the next() call inside an if statement and tried to find the error for more than 3 hours.

user.pre("save", function(next) {
    if(!this.trial){
        //do your job here
        next();
    }
}

When this.trial == true, next handler won't be reachable.

To prevent errors like this we should take care of branch coverage, reporters can show us untested codes. Your problem might be related with this too. Be sure you are calling next() if your document should be saved.

Fixed Version

user.pre("save", function(next) {
    if(!this.trial){
        //do your job here
    }
    next();
}
Footer answered 1/3, 2016 at 22:13 Comment(2)
Can we be realistic here and note that since your question itself makes no mention of a "pre save hook" then this is not really a solution that anyone was going to arrive at. Yes of course if the middleware continuation was not called then the code is just going to get stuck and not continue. And these are actually "callbacks" and not promises.Cremate
Thanks for saving my sanity... this very same thing happened and I've wasted like 3 hours trying to figure out WTH was going on...Selmaselman
B
13

This sounds nuts.. and I've been trying to work through this problem for hours. Looked at so many stack overflow posts.. it's unbelievable.

And you know what it was? I wasn't specifying the database at the end of the url.

So instead of

"mongodb://127.0.0.1:27017/test"

I had

"mongodb://127.0.0.1:27017

I wasted a whole day on this. I really wish I was given errors of some kind. Saving a record always returned ok. And in the database log, I was connecting ok. But I really needed to look at the details. Yes, it was connecting to the mongo instance, but not to the database itself. ugh!

Bogle answered 2/2, 2018 at 5:32 Comment(2)
Ohh man you saved life in 2020 :D Thanks I had the same mistake there, forgot to add DB name.Bon
In My Case the problem was <DB Name> and I left <> in <Password> like this. How Stupid I was. lolGalagalactagogue
D
5

Like Paul said. Most likely you are calling save on the 'req.user' object, which is not a Mongoose object. Make sure you are doing something like this:

//I am using your 'user' schema
var userModel = mongoose.model('User', user);
var User = mongoose.model('User');
var newUser = new User(req.user);
newUser.save(function(error, user){
   //your code
}
Disaster answered 1/3, 2016 at 21:28 Comment(1)
No this doesn't works, I am sure there is something wrong with .save()Ream
C
2

Just in case this happens to anyone else.

Another cause of this could be if you do not have an open connection to your mongodb instance. Check your output for the appropriate connection feedback.

[initandlisten] connection accepted from 127.0.0.1:40448 #1 (1 connection now open)

Capitally answered 11/8, 2017 at 17:42 Comment(1)
Jesus thank you.. was stuck on this for like 20 minsPlaten
W
1

I came across the same issue, turns out that instance.save() returns a promise. So all you need to do is handle the promise. Using async/await-

await instance.save()
Waldenburg answered 18/3, 2019 at 19:29 Comment(0)
A
0

modlename.save() does not accepts a callback anymore now you can solve this problem using Promises

newData.save().then(function(err) {
  if (!err) {
    res.send("Successfully Added to th DataBase.");
  } else {
    res.send(err);
  }
});
Arber answered 26/3, 2023 at 8:5 Comment(0)
N
0

It does not work for me now using if else statement for save(). I think now you can solve it using try catch statement

user.save().then(function (err) {
    try {
      res.render("User created succesfully");
    } catch (err) {
      console.log(err);
    }
  });
Nematode answered 17/5, 2023 at 6:21 Comment(1)
Hi, the author specifies in a comment that he has already found the solution. While answering, be sure to read carefully all commentss. Anyway, I asked the author to write a regular answer. Take a look here: how to answerHuston
M
0

The error "Unresolved function or method save()" indicates that the save() method is not recognized or available for the instance object. This error commonly occurs when the model object is not properly instantiated or imported.

Using inside try Catch Block

try {
   const savedProduct = await instance.save();
   ...
} catch (error) {
   ...
}

I was able to resolve the error this way

Montague answered 25/2 at 19:21 Comment(0)
S
0

The easiest fix i got is :> use findOne() instead to find() to get the instace . Then the instance.save will work just fine .

instance.save({validateBeforeSave:false})

Santinasantini answered 22/6 at 3:58 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Dogear
U
-2

for anyone having same error as me.. If you call .save() twice in very short time. the last call will be discarded. My problem was this.

//module usersave(userData)
{
  await userData.save()
}
//module A
{...todos
  moduleB(userData)
  ...some todos that doesn't take much time.
  await usersave(userData) //second call
}
//module B(userData)
{
 ...todos;
 await usersave(userData) // first call
}

=> Object.save() was called at module B, and instantly called again at module A. (it doesn't matter you made save module or just directly called Object.save() ). these kinds of call stack emits no error, and normal success return on both modules. However, since second call is evoked before the mongodb actually reflects the change, later call is just discarded. problem is that it returns as if they are actually saved so you can't catch an error.

solution : just put an await. await new Promise(r=>setTimeout(r,2000)) will do.

Unconscionable answered 24/4, 2020 at 3:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.