Mongoose Schema hasn't been registered for model
node.jsMongodbMongoosenode.js Problem Overview
I'm learning the mean stack and when I try to start the server using
npm start
I get an exception saying that:
schema hasn't been registered for model 'Post'. Use mongoose.model(name, schema)
here is my code inside /models/Posts.js
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
mongoose.model('Post', PostSchema);
as I can see the schema should be registered for the model 'Post', but what can be possibly causing the exception to be thrown?
Thanks in advance.
Edit: Here's the exception error
/home/arash/Documents/projects/personal/flapper-news/node_modules/mongoose/lib/index.js:323
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "Post".
Use mongoose.model(name, schema)
and here's the app.js code with the mongoose initialization:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
before the line:
app.use('/', routes);
node.js Solutions
Solution 1 - node.js
It's not an issue with model export. I had the same issue.
The real issue is that require statements for the models
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
were below the routes dependencies. Simply move the mongoDB dependencies above the routes dependencies. This is what it should look like:
// MongoDB
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/news');
require('./models/Posts');
require('./models/Comments');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
Solution 2 - node.js
If someone coudn't fix it with the approach of the correct answer (like me), try to look at the creation of the schema. I wrote the 'ref' as 'User', but the correct was 'user'.
Wrong:
createdBy: {
type: Schema.Types.ObjectId,
ref: 'User'
}
Correct:
createdBy: {
type: Schema.Types.ObjectId,
ref: 'user'
}
Solution 3 - node.js
IF YOU USE MULTIPLE mongoDB CONNECTIONS
beware that when using .populate() you MUST provide the model as mongoose will only "find" models on the same connection. ie where:
var db1 = mongoose.createConnection('mongodb://localhost:27017/gh3639');
var db2 = mongoose.createConnection('mongodb://localhost:27017/gh3639_2');
var userSchema = mongoose.Schema({
"name": String,
"email": String
});
var customerSchema = mongoose.Schema({
"name" : { type: String },
"email" : [ String ],
"created_by" : { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
});
var User = db1.model('users', userSchema);
var Customer = db2.model('customers', customerSchema);
Correct approach:
Customer.findOne({}).populate('created_by', 'name email', User)
Customer.findOne({}).populate({ path: 'created_by', model: User })
// you can pass the model NAME instead of model instance
Customer.findOne({}).populate({ path: 'created_by', model: 'User' })
Incorrect (produces "schema hasn't been registered for model" error):
Customer.findOne({}).populate('created_by');
Solution 4 - node.js
I used the following approach to solve the issue
const mongoose = require('mongoose');
const Comment = require('./comment');
const PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: Comment }]
});
mongoose.model('Post', PostSchema);
Please look, here ref
don't have string
type value, now it's referring to Comment
schema.
Solution 5 - node.js
Here's https://mongoosejs.com/docs/populate.html#cross-db-populate
It says we have to pass the model as a third argument.
For e.g.
//Require User Model
const UserModel = require('./../models/User');
//Require Post Model
const PostModel = require('./../models/Post');
const posts = await PostModel.find({})
.select('-__v')
.populate({
path: 'user',
select: 'name -_id',
model: UserModel
});
//or
const posts = await PostModel.find({})
.select('-__v')
.populate('user','name', UserModel);
Solution 6 - node.js
this problem happens when you use a model that depends on another model, but that other model didn't get registered yet.
a simple fix would be
adding model
to popualte instead of depending on ref
in the schema
=>> example
const jobs = await Job.find({}).populate({
path: "jobDescriptions",
model: JobDesc,
select: "list",
populate: {
path: "list",
select:"name list",
model: Skill,
},
});
Solution 7 - node.js
This error also pops up when we create wrong references (ref) between mongoose models.
In my case I was referring to the file name instead of model name.
eg:
const userModel = mongoose.model("user", userSchema);
We should refer to 'user' (model name) instead of 'User' (file name);
Solution 8 - node.js
The issue is with the refs, always make sure to refer the refs to whatever name your are exporting from the models.
// Model
const Task = mongoose.model('**Tasks**', taskSchema);
//Refs
userSchema.virtual('tasks', {
ref: '**Tasks**',
localField: '_id', // field in current model
foreignField: 'owner' // corresponding field in other model
});
Solution 9 - node.js
.\nodeapp\node_modules\mongoose\lib\index.js:452
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "users".
Use mongoose.model(name, schema)
at new MissingSchemaError
I got this error resolved when use setTimeout on server.js
mongoose.connect(env.get('mongodb.uri'), { useNewUrlParser: true })
.then(() => logger.info("MongoDB successfully connected"))
.catch(err => logger.error(err));
app.use(passport.initialize());
setTimeout(function() {
require("./src/utils/passport")(passport);
}, 3000);
Solution 10 - node.js
I was also facing the same problem. The solution to my problem was looking at the ref parameter which had a different name compared to the model I was actually exporting and hence no such model was found.
userSchema.virtual('tasks', {
ref: 'Task',
localField: '_id',
foreignField: 'owner'
})
Whereas what I had actually exported was :-
const Tasks = mongoose.model('Tasks', taskSchema)
module.exports = Tasks
After rectifying the Task
as Tasks
my problem was solved
Solution 11 - node.js
Elaborating on Rafael Grilli's answer above,
Correct:
var HouseSchema = new mongoose.Schema({
date: {type: Date, default:Date.now},
floorplan: String,
name:String,
house_id:String,
addressLine1:String,
addressLine2:String,
city:String,
postCode:String,
_locks:[{type: Schema.Types.ObjectId, ref: 'xxx'}] //ref here refers to the first parameter passed into mongoose.model()
});
var House = mongoose.model('xxx', HouseSchema, 'houseschemas');
Solution 12 - node.js
You should also check that you don't have dirty data in your database. I ended up with a document containing the lowercased version of the referenced model (user
instead of User
). This causes the error and is incredibly hard to track down.
Easy to fix with a quick mongo query:
db.model.updateMany({ approvedByKind: 'user' }, { $set: { approvedByKind: 'User' } })
Solution 13 - node.js
In my case, this issue because I haven't included the model or ref model into the application.
So you should required Post model
and Comment model
in your node application.
Solution 14 - node.js
Refer the same name that you refer in model name while creating new model.
For example: if I have mongoose model like:
var Post = mongoose.model("post",postSchema);
Then I have to refer to posts collection via writing ref:"post"
.
Solution 15 - node.js
My problem was sort out using the below
adminModel.findById(req.params.id).populate({ path: "users", model: userModel //User collection name })
Solution 16 - node.js
Just wanted to add that for me I was using destructuring when importing the Schema which was causing it to fail.
Correct
var intakeSchema = require('../config/models/intake')
Incorrect
var { intakeSchema } = require('../config/models/intake')
Solution 17 - node.js
You're not giving the model any value
In my case, I was using a model for which I didn't updated when making the MongoDB connection.
So, I had something like
const Device = require('../../models/device')
// make use of Device
with this connection
conn = await mongo.createConnection(conn,
[JobApplication, Job, User])
Fix
You have to add the model to the conn
when initiating the connection
conn = await mongo.createConnection(conn,
[JobApplication, Job, User, Device])
Note that I added Device
to the connection.
Solution 18 - node.js
import User from '..'
Customer.findOne({}).populate({ path: 'created_by', model: User })
This answer works for me. However You're going to have to import the model instead of setting it into cote
Solution 19 - node.js
I also facing same issue but i resolved by removing module.exports
> module.exports = mongoose.model('user', userSchema); // remove module.exports
> and use like:: mongoose.model('user', userSchema);
const mongoose = require('mongoose');
const ObjectId = require('mongoose').ObjectId;
var userSchema = new mongoose.Schema({
Password: { type: String },
Email: { type: String, required: 'This field is required.', unique:true },
songs: [{ type: ObjectId, ref: 'Songs'}]
});
// Custom validation for email
userSchema.path('Email').validate((val) => {
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
// module.exports = mongoose.model('user', userSchema); // remove 'module.exports ='
mongoose.model('user', userSchema); // resolved issue