Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot overwrite model once compiled Mongoose

Another reason you might get this error is if you use the same model in different files but your require path has a different case.

For example, in my situation I had require('./models/User') in one file, and then in another file where I needed access to the User model, I had require('./models/user').

I guess the lookup for modules & mongoose is treating it as a different file. Once I made sure the case matched in both it was no longer an issue.


The error is occurring because you already have a schema defined, and then you are defining the schema again. Generally what you should do is instantiate the schema once, and then have a global object call it when it needs it.

For example:

user_model.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var userSchema = new Schema({
   name:String,
   email:String,
   password:String,
   phone:Number,
   _enabled:Boolean
});
module.exports = mongoose.model('users', userSchema);          

check.js

var mongoose = require('mongoose');
var User = require('./user_model.js');

var db = mongoose.createConnection('localhost', 'event-db');
db.on('error', console.error.bind(console, 'connection error:'));
var a1= db.once('open',function(){
  User.find({},{},function (err, users) {
    mongoose.connection.close();
    console.log("Username supplied"+username);
    //doSomethingHere 
  })
});

insert.js

var mongoose = require('mongoose');
var User = require('./user_model.js');

mongoose.connect('mongodb://localhost/event-db');
var new_user = new User({
    name:req.body.name
  , email: req.body.email
  , password: req.body.password
  , phone: req.body.phone
  , _enabled:false 
});
new_user.save(function(err){
  if(err) console.log(err); 
});

I had this issue while 'watching' tests. When the tests were edited, the watch re-ran the tests, but they failed due to this very reason.

I fixed it by checking if the model exists then use it, else create it.

import mongoose from 'mongoose';
import user from './schemas/user';

export const User = mongoose.models.User || mongoose.model('User', user);

I had this issue while unit testing.

The first time you call the model creation function, mongoose stores the model under the key you provide (e.g. 'users'). If you call the model creation function with the same key more than once, mongoose won't let you overwrite the existing model.

You can check if the model already exists in mongoose with:

let users = mongoose.model('users')

This will throw an error if the model does not exist, so you can wrap it in a try/catch in order to either get the model, or create it:

let users
try {
  users = mongoose.model('users')
} catch (error) {
  users = mongoose.model('users', <UsersSchema...>)
}

If you are using Serverless offline and don't want to use --skipCacheInvalidation, you can very well use:

module.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);

I have been experiencing this issue & it was not because of the schema definitions but rather of serverless offline mode - I just managed to resolve it with this:

serverless offline --skipCacheInvalidation

Which is mentioned here https://github.com/dherault/serverless-offline/issues/258

Hopefully that helps someone else who is building their project on serverless and running offline mode.