title: MongoDB - Mongoose - TypeError: save is not a function
body: <p>I am attempting to perform an update to a MongoDB document (using mongoose) by first using .findById to get the document, then updating the fields in that document with new values.  I am still a bit new to this so I used a tutorial to figure out how to get it working, then I have been updating my code for my needs. Here is the tutorial: <a href="https://medium.com/netscape/mean-app-tutorial-with-angular-4-part-1-18691663ea96" rel="nofollow noreferrer">MEAN App Tutorial with Angular 4</a>. The original code had a schema defined, but my requirement is for a generic MongoDB interface that will simply take whatever payload is sent to it and send it along to MongoDB.  The original tutorial had something like this:</p>
  
  <pre><code>exports.updateTodo = async function(todo){
      var id = todo.id
  
      try{
          //Find the old Todo Object by the Id
  
          var oldTodo = await ToDo.findById(id);
      }catch(e){
          throw Error("Error occured while Finding the Todo")
      }
  
      // If no old Todo Object exists return false
      if(!oldTodo){
          return false;
      }
  
      console.log(oldTodo)
  
      //Edit the Todo Object
      oldTodo.title = todo.title
      oldTodo.description = todo.description
      oldTodo.status = todo.status
  
  
      console.log(oldTodo)
  
      try{
          var savedTodo = await oldTodo.save()
          return savedTodo;
      }catch(e){
          throw Error("And Error occured while updating the Todo");
      }
  }
  </code></pre>
  
  <p>However, since I don't want a schema and want to allow anything through, I don't want to assign static values to specific field names like, title, description, status, etc.  So, I came up with this:</p>
  
  <pre><code>exports.updateData = async function(update){
      var id = update.id
  
      // Check the existence of the query parameters, If they don't exist then assign a default value
      var dbName = update.dbName ? update.dbName : 'test'
      var collection = update.collection ? update.collection : 'testing'; 
  
      const Test = mongoose.model(dbName, TestSchema, collection);
  
      try{
          //Find the existing Test object by the Id
          var existingData = await Test.findById(id);
      }catch(e){
          throw Error("Error occurred while finding the Test document - " + e)
      }
  
      // If no existing Test object exists return false
      if(!existingData){
          return false;
      }
  
      console.log("Existing document is " + existingData)
  
      //Edit the Test object
      existingData = JSON.parse(JSON.stringify(update))
  
      //This was another way to overwrite existing field values, but
      //performs a "shallow copy" so it's not desireable
      //existingData = Object.assign({}, existingData, update)
  
      //existingData.title = update.title
      //existingData.description = update.description
      //existingData.status = update.status
  
      console.log("New data is " + existingData)
  
      try{
          var savedOutput = await existingData.save()
          return savedOutput;
      }catch(e){
          throw Error("An error occurred while updating the Test document - " + e);
      }
  }
  </code></pre>
  
  <p>My original problem with this was that I had a lot of issues getting the new values to overwrite the old ones.  Now that that's been solved, I am getting the error of "TypeError: existingData.save is not a function".  I am thinking the data type changed or something, and now it is not being accepted.  When I uncomment the static values that were in the old tutorial code, it works.  This is further supported by my console logging before and after I join the objects, because the first one prints the actual data and the second one prints [object Object].  However, I can't seem to figure out what it's expecting.  Any help would be greatly appreciated.</p>
  
  <p><strong>EDIT:</strong> I figured it out.  Apparently Mongoose has its own data type of "Model" which gets changed if you do anything crazy to the underlying data by using things like JSON.stringify.  I used Object.prototype.constructor to figure out the actual object type like so:</p>
  
  <pre><code>console.log("THIS IS BEFORE: " + existingData.constructor);
  existingData = JSON.parse(JSON.stringify(update));
  console.log("THIS IS AFTER: " + existingData.constructor);
  </code></pre>
  
  <p>And I got this:</p>
  
  <pre><code>THIS IS BEFORE: function model(doc, fields, skipId) {
    model.hooks.execPreSync('createModel', doc);
    if (!(this instanceof model)) {
      return new model(doc, fields, skipId);
    }
    Model.call(this, doc, fields, skipId);
  }
  THIS IS AFTER: function Object() { [native code] }
  </code></pre>
  
  <p>Which showed me what was actually going on.  I added this to fix it:</p>
  
  <pre><code>existingData = new Test(JSON.parse(JSON.stringify(update)));
  </code></pre>
  
  <p>On a related note, I should probably just use the native MongoDB driver at this point, but it's working, so I'll just put it on my to do list for now.</p>