mongoose Missing schema error while populating - node.js

I am building an app with express using mongoose as ORM for my MongoDB database.
I have 2 models located in separate files : User and Posts.
User.js model looks like
var mongoose = require('mongoose'),
moment = require('moment'),
Schema = mongoose.Schema,
UserSchema = new Schema({
created_at: {type: Date, default: moment()),
name: String
});
module.exports = mongoose.model('user', UserSchema);
and the Posts.js model
var mongoose = require('mongoose'),
moment = require('moment'),
Schema = mongoose.Schema,
PostSchema = new Schema({
created_at: {type: Date, default: moment()},
user: {type: Schema.Type.ObjectId, ref: 'User'}
});
I call them in controllers in separate files that looks like
var Post = require('../models/User'),
User = require('../models/Posts');
Post.find().populate('user').exec();
This population returns me a MissingSchema error that says :
MissingSchemaError: Schema for model 'Posts' hasn't been registerd.
The connection to the database is in the main file : app.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1/database');
Can anyone tell me what's wrong with my code?

Because your reference is for "User", I think you just have to declare your first model with correct Typpo
module.exports = mongoose.model('User', UserSchema);
instead of
module.exports = mongoose.model('user', UserSchema);
Hope it helps.

Related

Schema has not been registered error on population

When I'm trying to populate , this error is coming:
" MissingSchemaError: Schema hasn't been registered for model "
My models:
/models/course.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user')
var courseSchema = Schema({
courseName:String,
price:Number,
type:String,
_offeredBy:{type:Schema.Types.ObjectId,ref:User}
});
module.exports = mongoose.model("Course",courseSchem
models/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var findOrCreate = require('mongoose-findorcreate')
var Course = require('./course')
var userSchema = Schema({
email:{type:String},
password:{type:String},
courseOffered:[{type:Schema.Types.ObjectId,ref:Course}]
});
module.exports = mongoose.model('User',userSchema);
routes/index.js
var Course = require('../models/course');
var User = require('../models/user');
var express = require('express');
var router = express.Router();
router.get('/user/profile',isLoggedIn,function(req,res,next){
res.render('user/profile',{csrfToken:req.csrfToken(),message:""})
});
router.post('/user/profile',isLoggedIn,function(req,res,next){
var courseInfo = req.body;
var newCourse = new Course();
newCourse.courseName = courseInfo.coursename;
newCourse.price = courseInfo.price;
newCourse.type = courseInfo.type;
newCourse._offeredBy = req.user;
newCourse.save(function(err,result){
if(err){
res.redirect('/user/profile');
}
});
Course
.findOne({courseName:courseInfo.coursename})
.populate('_offeredBy')
.exec(function(err,course){
if(err){
res.redirect('/user/profile');
}
});
});
Course is getting saved in the database, but the error is coming due to pouplating. I'm not writing the app.js, mongodb connections are made in app.js file.
Your models are trying to load another model which itself then tries to load the other model.
In your schemas you should set the refs as strings like this:
var courseSchema = Schema({
courseName: String,
price: Number,
type: String,
_offeredBy: { type:Schema.Types.ObjectId, ref: 'User' }
});
var userSchema = Schema({
email: String,
password: String,
courseOffered: [{ type: Schema.Types.ObjectId, ref: 'Course' }]
});
You can then remove the lines to require the other model within each model file. They are both loaded in 'routes/index.js' before being used.
Note: newCouse.save() is asynchronous so you should do you Course.findOne().populate() inside the 'save' callback.

mongoose schema is broken into several files, how to require?

doing mongoose db in nodejs.
i got an error: "schema is not defined".
in my model i have 2 files for different schemas: user and product, they look smth like:
'use strict';
var mongoose = require('mongoose'),
bcrypt = require("bcryptjs");
var UsersSchema = new Schema({
name: String,
email: String,
telephone: Number,
createdAt: {type: Date, default: Date.now},
updatedAt: {type: Date, default: Date.now}
});
var userModel = mongoose.model('User', userSchema);
module.exports.userModel = userModel;
I have nothing in routes, and in app.js, I've got:
var users = mongoose.model('User', userSchema);
var products = mongoose.model('Product', productSchema);
Previously I tried:
var users = require('../models/userSchema');
var products= require('../models/productSchema');
any advise? thanks
To resolve the "schema is not defined" issue, import the Mongoose schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
For the exports, I would suggest the following. No reason to nest this additionally, when you're defining one model per file:
var userModel = mongoose.model('User', userSchema);
module.exports = userModel;
Then you can require the model in other files as shown in your post, e.g.:
var users = require('../models/userSchema');
You can get rid of requiring mongoose models in your code by putting them in app.
Add index.js file in the folder (let's say 'models') where user.js and product.js are placed:
var fs = require('fs');
var path = require('path');
module.exports = function(app) {
app.models = app.models || {};
fs.readdirSync(__dirname).forEach(function(file) {
if (file !== "index.js" && path.extname(file) === '.js'){
var model = require(path.join(__dirname,file))(app);
app.models[model.modelName] = model;
}
});
};
Change user.js (and similarly product.js) file to
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require("bcryptjs");
module.exports = function(){
var UsersSchema = new Schema({
name: String,
email: String,
telephone: Number,
createdAt: {type: Date, default: Date.now},
updatedAt: {type: Date, default: Date.now}
});
return mongoose.model("User", UsersSchema); //the name "User" here will be stored as key in app.models and its value will be the model itself
};
And in app.js insert a line
require("./app/models")(app) //pass app to the index.js, which will add models to it
Now you can use app.models.User and app.models.Product across the application.

saving unstructured data in mongoose

I am able to save request the data if I explicitly define in my express model the structure, but I am not able to save record if I do not explicitly define the data structure.
For example I am able to save if I have this in my model
....
module.exports = mongoose.model('Form', new Schema({
name: String,
password: String,
admin: Boolean
}));
...
...
but I am not able to save it if I have it like this
module.exports = mongoose.model('Form', new Schema());
Here is my model
// get an instance of mongoose and mongoose.Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// set up a mongoose model and pass it using module.exports
module.exports = mongoose.model('Form', new Schema());
And here is my Router
apiRouter.post('/forms/createForm', function(req, res) {
var form = new Form(req.body);
form.save(function(err) {
if (err) throw err;
console.log('Form saved successfully');
res.json({ success: true });
});
});
Thanks
Ok I got that working.
There is a strict false option that I can use to define the schemaless structure.
Thats how I did it:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// set up a mongoose model and pass it using module.exports
module.exports = mongoose.model('Form', new Schema({}, { strict: false} ));

Creating a Foreign Key relationship in Mongoose

I'm beginning with Mongoose and I want to know how to do this type of configuration:
A recipe has different ingredients.
I have my two models:
Ingredient and Recipe:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var IngredientSchema = new Schema({
name: String
});
module.exports = mongoose.model('Ingredient', IngredientSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var RecipeSchema = new Schema({
name: String
});
module.exports = mongoose.model('Recipe', RecipeSchema);
Check Updated code below, in particular this part:
{type: Schema.Types.ObjectId, ref: 'Ingredient'}
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var IngredientSchema = new Schema({
name: String
});
module.exports = mongoose.model('Ingredient', IngredientSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var RecipeSchema = new Schema({
name: String,
ingredients:[
{type: Schema.Types.ObjectId, ref: 'Ingredient'}
]
});
module.exports = mongoose.model('Recipe', RecipeSchema);
To Save:
var r = new Recipe();
r.name = 'Blah';
r.ingredients.push('mongo id of ingredient');
r.save();

How does this line in a single file of a node express app allow the variable to be accessed in other files?

I have a node app using Express and Mongoose. I have seen this line in demo app but I don't understand how it is working.
app.js
require('./db.js');
require('./routes.js')(app);
db.js
exports = mongoose = require('mongoose');
mongoose.connect('localhost:27017/test');
exports = Schema = mongoose.Schema;
require('./models.js')
models.js
var ArticleSchema = new Schema({
title : {type : String, default : '', trim : true}
, body : {type : String, default : '', trim : true}
, user : {type : Schema.ObjectId, ref : 'User'}
, created_at : {type : Date, default : Date.now}
})
mongoose.model('Article', ArticleSchema);
routes.js
var Article = mongoose.model('Article');
module.exports = function(app){
app.get('/new', function(req, res){
var article = new Article({});
res.render('new', article);
});
};
How are the variables mongoose and schema available in the other modules like models.js and routes.js?
This code all still works if I change the exports = mongoose = require('mongoose'); line I saw in the demo to either of these which I am more familiar with.
module.exports = mongoose = require('mongoose');
exports.anything = mongoose = require('mongoose');
The variable name in the middle of the three assignments is what is available in other files.
Can someone explain what is going on here and how it is working?
Thanks!
Try this:
app.js
var db = require('./db.js');
require('./routes.js')(app, db);
db.js
var mongoose;
module.exports.mongoose = mongoose = require('mongoose');
mongoose.connect('localhost:27017/test');
module.exports.Schema = mongoose.Schema;
require('./models.js')(module.exports);
models.js
module.exports = function (db) {
var ArticleSchema = new db.Schema({
title : {type : String, default : '', trim : true}
, body : {type : String, default : '', trim : true}
, user : {type : db.Schema.ObjectId, ref : 'User'}
, created_at : {type : Date, default : Date.now}
})
db.mongoose.model('Article', ArticleSchema);
};
routes.js
module.exports = function (app, db) {
var Article = db.mongoose.model('Article');
app.get('/new', function(req, res){
var article = new Article({});
res.render('new', article);
});
};

Resources