Mongoose: Fails to save object with invalid ID without raising Error

Created on 21 Jan 2017  路  4Comments  路  Source: Automattic/mongoose

Do you want to request a feature or report a bug?
Bug
What is the current behavior?
When a MongoDB record was created with an _id as String instead of ObjectID, Mongoose fails to update the record but doesn't return an Error and instead returns a false record

var mongoose = require("mongoose")
mongoose.Promise = global.Promise
mongoose.connect("mongodb://localhost/test")
var db = mongoose.connection
db.on("error", function(err){
  console.log("MongoDB connection error:")
})
db.once("open", function() {
  console.log("Connection to MongoDB successful")
})

// Create a user model to use for testing
var userSchema = new mongoose.Schema({
  name: String,
  email:{
    type:String,
    index:true,
    unique:true,
    required:true
  }
})
var user = mongoose.model("user",userSchema)

// Create a user that we want to save
var userToEnter = {
  _id: "5845368bcbd64060bc142bba",
  name:"Foo",
  email:"myemail@example"
}

// If the user is entered into MongoDB directly (instead of via Mongoose)
// the _id is not casted to ObjectID, but saved as a String
user.collection.insert(userToEnter)
// => { "_id": "5845368bcbd64060bc142bba", "name": "Foo", "email": "myemail@example" }

// Now try to update the record
user.findOne({ email:"myemail@example" }, function(err,record){
  if (err){
    console.log(err)
  } else if (record) {
    updateUser(record)
  } else {
    console.log("No user found")
  }
})

function updateUser(record){
  record.name = "Bar"
  record.save(function(err,newRecord,count){
    if (err){
      console.log(err)
    } else {
      userUpdated(newRecord,count)
    }
  })
}

function userUpdated(newRecord,count){
  // The count is 0 and the returned object contains the saved changes.
  // But the changes are not saved in MongoDB
  console.log("Number of saved records: "+count)
  console.log("Record returned from Model.save: "+JSON.stringify(newRecord))
  console.log("Name: "+newRecord.name)
  user.findOne({ email:"myemail@example" }, function(err,record){
    if (err){
      console.log(err)
    } else {
      // MongoDB still contains the initial record
      console.log("User after saving:")
      console.log(JSON.stringify(record))
      console.log("Name: "+record.name)
    }
  })
}

// Expected either an Error or:
//    => Number of saved records: 1
//    => Record returned from Model.save: { "_id": "5845368bcbd64060bc142bba", "name": "Bar", "email": "myemail@example" }
//    => Name: Bar
//    => User after saving:
//    => { "_id": "5845368bcbd64060bc142bba", "name": "Bar", "email": "myemail@example" }
//    => Name: Bar

// Observed:
//    => Number of saved records: 1
//    => Record returned from Model.save: { "_id": "5845368bcbd64060bc142bba", "name": "Bar", "email": "myemail@example" }
//    => Name: Bar
//    => User after saving:
//    => { "_id": "5845368bcbd64060bc142bba", "name": "Foo", "email": "myemail@example" }
//    => Name: Foo

What is the expected behavior?
Mongoose should return an Error if the record can't be saved

Please mention your node.js, mongoose and MongoDB version.
Node v7.0.0
Mongoose Version: 4.7.7

confirmed-bug

Most helpful comment

So in 4.8.0 there will be an option for this:

var userSchema = new mongoose.Schema({
  name: String,
  email:{
    type:String,
    index:true,
    unique:true,
    required:true
  }
}, { saveErrorIfNotFound: true })

Going to release 4.8.0 within the next week so look forward to that :+1:

All 4 comments

Thanks, that should probably throw an error.

So in 4.8.0 there will be an option for this:

var userSchema = new mongoose.Schema({
  name: String,
  email:{
    type:String,
    index:true,
    unique:true,
    required:true
  }
}, { saveErrorIfNotFound: true })

Going to release 4.8.0 within the next week so look forward to that :+1:

馃憤 Awesome. Thanks for the quick fix!

Can't claim too much credit, implemented this feature for #4004 and supporting plugins that could modify the query used to save a doc. That's how you know a feature is valuable, fixes bugs you haven't even found yet :+1: :rocket:

Was this page helpful?
0 / 5 - 0 ratings