mongoose schema is broken into several files, how to require? - node.js

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.

Related

mongoose Missing schema error while populating

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.

Able to add to database in MongoDB but not mongoose

I am learning about Mongoose. I am working along this tutorial and running into a stumbling block with adding entries to my database, run through Heroku MongoDB. I am able to add to the existing collection "test1" when I load the app 'trywithmongodb' but I in my Heroku mLab console I do not see anything added to any collections when I access the page "trywithmongoose". Help? Here is the relevant code for in index.js:
var express = require('express');
var mongoose = require("mongoose");
var mongo = require('mongodb').MongoClient;
app.get("/trywithmongodb", function(request,response){
response.send("Looking at the /trywithmongodb page");
var configDB = require('./config/database.js');
//add to the database
mongo.connect(configDB.url , function(err, db) {
var shorturl = db.collection("test1");
var date = new Date();
var newsitejson={original_url: "accessed at", site_number: date.getHours()+":"+date.getMinutes()}
shorturl.insert(newsitejson)
db.close()
})
});
app.get('/trywithmongoose', function (request, response) {
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);
// grab the user model
var User = require('./app/models/user');
// create a new user
var newUser = User({
name: 'Peter ',
username: 'peter45',
password: 'willbehashed',
admin: true
});
// save the user
newUser.save(function(err) {
if (err) throw err;
console.log('User created!');
});
response.send("You are looking at /trywithmongoose");
});
And here's the full file user.js for the schema:
// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var userSchema = new Schema({
name: String,
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
admin: Boolean
});
// the schema is useless so far
// we need to create a model using it
var User = mongoose.model('User', userSchema);
// make this available to our users in our Node applications
module.exports = User;

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.

1 of 2 Mongoose schema not getting initialized

I am new to Node and MongoDB. I am using mongoose to create schemas on Mongo. I have created two schemas in 1 models.js file as shown below
var mongoose = require('mongoose');
var postSchema = new mongoose.Schema({
username: String,
text: String,
created_at: {type: Date, default: Date.now}
});
var userSchema = new mongoose.Schema({
username: String,
password: String,
created_at: {type: Date, default: Date.now}
});
//declaring a model which has schema userSchema
mongoose.model("User", userSchema);
mongoose.model("Post", postSchema);
The problem is that my user schema is getting initialized and works fine. But the posts schema is a problem.
This is the error that I get while starting the server:
C:\Users\rohit\Desktop\projects\chirp\module4\start\node_modules\mo
throw new mongoose.Error.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "Post".
Here is my snippet from the api.js that actually calls post schema to make database queries
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Post = mongoose.model('Post');
...
router.route('/posts')
.get (function(req, res){
Post.find(function(err, data){
if(err){
return res.send(500, err)
}
return res.send(data)
})
})
Here, is the code snippet from my auth.js file that uses the User Schema and it works fine
var LocalStrategy = require('passport-local').Strategy;
var bCrypt = require('bcrypt-nodejs');
var mongoose = require('mongoose');
var User = mongoose.model('User');
var Post = mongoose.model('Post');
module.exports = function(passport){
// Passport needs to be able to serialize and deserialize users to support persistent login sessions
passport.serializeUser(function(user, done) {
console.log('serializing user:',user._id);
return done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user){
if (err){
return done(err, false)
}
if(!user){
return done('User not found', false)
}
return done(user, true);
})
});
You are not loading your models (User and Post) in your models.js.
Add the following lines after var mongoose = require('mongoose');:
var User = require('./models/user.js'); <-- type your user.js model path here
var Post = require('./models/post.js'); <-- type your post.js model path here

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();

Resources