Problem with mongoose schema reference in Node - node.js

I'm new to Node, Mongoose and to everything related to Backend. I ran into a problem recently. I couldn't figure it out as the same code in exercise files of a development course seems to be the same. Nevertheless problem still doesn't resolve. Thing I'm trying to do, coding along with the tutorials, is that I want to define a Mongoose model for comments in the Mongo database for every campground section that I have displayed on the page. I have models folder where I define models for campground and comments, a seeds.js file where I dynamically add data to campgrounds (in order for it to appear with comments instantly) and then add comments. Here is what the actual code looks like for these files:
app.js-->
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var mongoose = require('mongoose');
var Campground=require("./models/campground");
var seedDB = require("./seeds");
var PORT = process.env.IP || 3200;
seedDB();
mongoose.connect('mongodb://localhost/yelp_camp', { useNewUrlParser: true },
(err, res) => {
if (err) throw err;
console.log('Database online');
});
app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");
//schema
app.get("/", function (req, res) {
res.render("landing");
});
app.get("/campgrounds/tornike", function (req, res) {
//get all campgrounds
res.send(Campground.name);
});
app.get("/campgrounds", function (req, res) {
//get all campgrounds
Campground.find({}, function (err, camp) {
if (err) {
console.log("ERROR");
console.log(err);
} else {
res.render("index", { campgrounds: camp });
}
});
});
app.post("/campgrounds", function (req, res) {
var name = req.body.name;
var image = req.body.image;
var desc = req.body.description;
var newCampground = { name: name, image: image, description:desc };
//create new camp and save to database
Campground.create(newCampground, function (err, newlyCreated) {
if (err) {
console.log(err);
} else {
res.redirect("/campgrounds");
}
});
});
app.get("/campgrounds/new", function (req, res) {
res.render("new.ejs");
});
//shows more info about camp
app.get("/campgrounds/:id", function (req, res) {
//find camp with provided id
Campground.findById(req.params.id, function (err, foundCampground) {
if (err) {
console.log(err);
} else {
//render show template
res.render("show", { campground: foundCampground });
}
});
});
app.listen(PORT, process.env.IP, function () {
console.log("camp");
});
seeds.js ---->
var mongoose = require("mongoose");
var Campground = require("./models/campground");
var Comment = require("./models/comment");
var data = [
{
name: "something",
image: "image URL",
description: "blah blah bla1"
},
{
name: "something",
image: "image URL",
description: "blah blah bla2"
},
{
name: "something",
image: "image URL",
description: "blah blah bla3"
}
];
function seedDB() {
Campground.deleteMany({}, function(err) {
console.log("removed camps");
data.forEach(function(seed) {
Campground.create(seed, function(err, data) {
if (err) {
console.log(err);
} else {
console.log("added campground");
Comment.create(
{
text: "dubdabdubadah",
author: "Homer"
},
function(err, comment) {
if (err) {
console.log(err);
} else {
campground.comments.push(comment);
campground.save();
console.log("Created new comment");
}
}
);
}
});
});
});
}
module.exports = seedDB;
comment.js --->
var mongoose = require("mongoose");
var commentSchema= new mongoose.Schema({
text:String,
author:String
});
module.exports=mongoose.model("Comment", commentSchema);
campground.js ---->
var mongoose = require("mongoose");
var campgroundSchema = new mongoose.Schema({
name: String,
image: String,
description: String,
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
module.exports = mongoose.model("Campground", campgroundSchema);
Error occurs in the seeds.js file on this line campground.comments.push(comment);
it looks like this:
[nodemon] starting `node app.js`
camp
Database online
removed camps
added campground
added campground
added campground
events.js:183
throw er; // Unhandled 'error' event
^
ReferenceError: campground is not defined
I can't actually get my head around this one as when comparing the code to the exercise files code - it is the same. The only thing I can think of is the versions of mongoose express or something else may not be relevant or some methods deprecated, but honestly no idea what's wrong. I've been trying to solve it for several days. any idea people ?

The error message is telling you that you haven't defined a variable named campground, which is correct, as you haven't.
To fix this, change data to campground in your Campground.create callback:
Campground.create(seed, function(err, campground) {

Related

how to insert data in multiple mongodb collections using mongoose & node.js

i am new in node.js. I'm trying to store three different objects in collection in mongodb using node.js.
index.js
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var app = express();
var control = require('./controllers/controller');
var port = 3200;
mongoose.connect(
'mongodb://localhost:27017/create-company',
{useNewUrlParser: true},
err => {
if(err) throw err;
console.log('connection successfully');
}
)
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({extended: true}));
app.use('/api', control);
app.listen(port, function(){
console.log('start your server on: ', port);
});
model.js
var mongoose = require('mongoose');
var CompanySchema = new mongoose.Schema({
companyname: String,
founder: String,
contact: String,
location: String
});
var company = mongoose.model("company", CompanySchema);
var BranchSchema = new mongoose.Schema({
branchname: String,
branchmanger: String,
contact: String,
location: String
});
var branch = mongoose.model('branch', BranchSchema);
var UserSchema = new mongoose.Schema({[enter image description here][1]
username: String,
userrole: String,
age: Number
});
var user = mongoose.model('user', UserSchema);
module.exports = {
company: company,
branch: branch,
user: user
}
controller.js
var express = require('express');
var router = express.Router();
var company = require('../models/model');
router.post('/create_company', function (req, res) {
var new_company = new company.company(req.body);
var new_branch = new company.branch(req.body);
var new_user = new company.user(req.body);
new_company.save(function (err, data) {
if (err)
res.send(data);
console.log(data);
});
new_branch.save(function (err, data) {
if (err)
res.send(data);
console.log(data);
});
new_user.save(function (err, data) {
if (err)
res.send(data);
console.log(data);
});
});
i am pass data to postman like this:
[{
"companyname": "stack",
"founder": "alex",
"contact": "1234567890",
"location": "in"
},
{
"branchname": "am",
"branchmanager": "abc",
"contact": "8754216523",
"location": "inn"
},
{
"username": "xyz",
"userrole": "admin",
"age": "23"
}]
enter image description here
There are three problems here:
You are attempting to create a new document by passing the entire body to the constructor. You need to pass the correct array element to it's respective constructor.
var new_company = new company.company(req.body[0]);
var new_branch = new company.branch(req.body[1]);
var new_user = new company.user(req.body[2]);
You are attempting to send a response more than once. You need to coordinate the callbacks so that you send the response after they all have completed. I suggest you use promises to accomplish this, fortunately Mongoose supports promises.
Promise.all([
new_company.save(),
new_branch.save(),
new_user.save()
]).then(function (data) {
res.send(data);
console.log(data);
});
You are not handling the error correctly. Your if (err) statement will cause res.send(data) to be called when there is an error, this is certainly not desired. Using the promise based method defined above error handling is very simple.
Promise.all([
new_company.save(),
new_branch.save(),
new_user.save()
]).then(function (data) {
res.send(data);
console.log(data);
}).catch(function (err) {
res.status(400).send('Uh oh! Something bad happened.');
console.error(err);
});
If you use ES6 syntax you can write a synchronous looking route, which may be more familiar if you are coming from a different language:
router.post('/create_company', async (req, res) => {
try {
const [company, branch, user] = req.body;
const data = await Promise.all([
new company.company(company).save(),
new company.branch(branch).save(),
new company.user(user).save()
]);
res.send(data);
} catch (err) {
res.status(400).send('Uh oh! Something bad happened.');
console.error(err);
}
});

Undefined: req.file() outputs undefined even when using upload.single() middleware

// Models
var mongoose = require('mongoose');
var ProfileSchema = new mongoose.Schema({
fullName: {
type: String,
required: true
}
// profileImage: {type: String, required: true}
});
module.exports = mongoose.model('Profile', ProfileSchema)
// Controllers
var Profile = require('../models/profile');
var multer = require('multer');
var upload = multer({dest: 'uploads/'});
exports.createProfile = (upload.single('profileImage'), function (req, res, next) {
var profileData = {
fullName: req.body.fullName,
// profileImage: req.file
}
console.log(req.file);
console.log('req.file: ', JSON.stringify(req.file));
console.log(profileData);
Profile.create(profileData, function (err, profile) {
if (err) {
// console.log(err);
res.end();
return;
// res.send(err);
}
Profile.create(function (err, profiles) {
if (err) {
res.end();
// res.send(err);
return;
}
res.json(profileData);
});
});
});
I'm trying to use middleware to add text and image at the same time in the MongoDB database. However, my fields aren't populated and when I try to print it out in the console it says req.file(): undefined. I've researched on the other issues and it states using 'upload.single()' will solve the problem. In my case, it didn't! The first section is my model view(Schema), the second section is my controllers' view.

Post request work with one collection but not with the another using mongodb nodejs?

I am trying to build a simple rest api. Firstly, I have 2 collections books and genres. once I post using postman in genres it post with no problems but once I post into books collection the post requesting time take about 2 minutes(which consider too much) then it return with connection error with knowing the server is remain working.
app
// Tools to be used in the web development
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
app.use(bodyParser.json());
Genre = require('./models/genre.js');
Book = require('./models/book.js');
let conn = mongoose.connection;
conn.openUri('mongodb://localhost/bookstore');
conn.on('error', err => console.error('mongodb connection error',
err));
conn.on('connected', () => console.info(`Connected to mongodb`));
conn.on('disconnected', () => console.info('Disconnected from
mongodb'));
// Routing to specific pages:
app.get('/', function(req, res){
res.send('Hello World');
});
app.get('/api/genres', function(req , res){
Genre.getGenres(function(err, genres){
if(err){
throw err;
}
res.json(genres);
})
});
app.get('/api/books', function(req , res){
Book.getBooks(function(err, books){
if(err){
throw err;
}
res.json(books);
})
});
app.get('/api/books/:_id', function(req , res){
Book.getBookById(req.params._id, function(err, book){
if(err){
throw err;
}
res.json(book);
})
});
app.post('/api/genres', function(req , res){
var genre = req.body;
Genre.addGenre(genre, function(err, genre){
if(err){
throw err;
}
res.json(genre);
})
});
app.post('/api/books', function(req , res){
var book = req.body;
Book.addBook(function(err, book){
if(err){
throw err;
}
res.json(book);
})
});
//Specify the listening port
app.listen(3666);
//Display the url on the termianl
console.log('Server Running On http://localhost:3666');
Book
var mongoose = require('mongoose');
//Book Schema
var bookSchema = mongoose.Schema({
title:{
type: String,
requires: true
},
genre:{
type: String,
required: true
},
description:{
type: String
},
author:{
type: String,
required: true
},
publisher:{
type: String,
required: true
},
create_date:{
type: Date,
default: Date.now
}
});
var Book = module.exports = mongoose.model('Book', bookSchema);
module.exports.getBooks = function(callback, limit){
Book.find(callback).limit(limit);
}
module.exports.getBookById = function(id, callback){
Book.findById(id, callback);
}
//add genre
module.exports.addBook = function(book, callback){
Book.create(book, callback);
}
and the postman request
and database
Notice: once I post request in genres I works but once I post for the book nothing happen.
Your addBook function takes two parameters: a book object and a callback
//add genre
module.exports.addBook = function(book, callback){
Book.create(book, callback);
}
But, while calling it, you have only passed a callback. You can try to use the below code:
app.post('/api/books', function(req , res){
var book = req.body;
Book.addBook(book, function(err, book){
if(err){
throw err;
}
res.json(book);
})
});

In my post req of comment, I want to update the values of reviews which consist of userid and comments

I am trying to update my Event. The Event Schema is shown below. How can I push the values as I desire? I am new to this. So, facing some difficulties. Thanks in advance. I want to post it in that id whose id matches and update the comment section as well as userid.
server.js
var express= require('express');
var bodyParser= require('body-parser');
var morgan = require('morgan');
var config=require('./config');
var app= express();
var mongoose=require('mongoose');
var lodash= require('lodash');
var underscore= require('underscore');
//var User=require('./database/user')
mongoose.connect('mongodb://localhost:27017/db',function(err){
if(err){
console.log(err);
}
else{
console.log("connected!");
}
});
//res.json({message:" " })
app.use(bodyParser.urlencoded({extended: true })); //if false then parse only strings
app.use(bodyParser.json());
app.use(morgan('dev'));//log all the requests to the console
var api=require('./app/routes/api')(app,express,underscore,lodash);
app.use('/api',api);
app.get('*',function(req,res){
// res.sendFile(__dirname + '/public/views/index.html');
}); // * means any route
app.listen(config.port,function(err){
if(err){
console.log(err);
}
else{
console.log("The server is running");
}
});
api.js
var User= require('../models/user');
var Event=require('../models/event');
var config=require('../../config');
var secret=config.secretKey;
module.exports=function(app,express,underscore,lodash) {
var api = express.Router();
// app.use()
api.post('/signup', function (req, res) {
var user = new User({
name: req.body.name,
username: req.body.username,
password: req.body.password
});
user.save(function (err) {
if (err) {
res.send(err);
return;
}
res.json({
message: 'User created!'
});
});
});
api.get('/users', function (req, res) {
User.find({}, function (err, users) {
if (err) {
res.send(err);
return;
}
res.json(users);
});
});
api.post('/eventfeed', function (req, res) {
var event = new Event({
name: req.body.name,
location: req.body.location,
description: req.body.description,
price: req.body.price,
rating: req.body.rating
});
event.save(function (err) {
if (err) {
res.send(err);
return;
}
res.json({
message: 'Event created!'
});
});
});
api.get('/event', function (req, res) {
Event.find({}, function (err, event) {
if (err) {
res.send(err);
return;
}
res.json(event);
});
});
api.post('/comment',function(req,res,com){
User.findByIdAndUpdate({ _id: req.body.id },
{ $push: { userid:req.body.id,comment: req.body.favourite }},
res.json(com)) ;
});
return api;
}
event.js
var mongoose= require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var EventSchema = new Schema({
name: String,
location: String,
description:String,
price: Number,
rating: Number,
reviews:[{userid:String,
comment: [String]}]
});
module.exports= mongoose.model('Event',EventSchema);
In your "addfavorites" controller, use "$push" instead of "$set". This let's you add something to an array in the database, just like the usual push function on Arrays.
Look e.g. here for an example: http://blog.ocliw.com/2012/11/25/mongoose-add-to-an-existing-array/
(There are some extra options "safe: true" etc. you can use to make extra sure there is no overriding).
You are missing curly braces of $push
So,
api.post('/addfavourites', function(req, res) {
// _id: req.body.id;
User.findByIdAndUpdate({ _id: req.body.id },
{ $push: { favourites: req.body.favourite }},
{ upsert: true },
function(fav) { res.json(fav); });
});
It should work now.
BTW i also found some missing brackets in your code.
Link to Syntax Specification

How do I pass multiple models into a view?

I am easily and successfully passing a single model into a view in one of my express routes like this:
exports.locations = function(req, res){
Location.find(function(err, results) {
res.render('locations', { title: 'Locations', locations: results });
});
};
I have another route where I need to pass 2 result sets into the view, how do I do that? I have tried doing this, but it doesn't seem to be working:
exports.locationdetail = function(req, res) {
var packages = Package.find();
Location.findById(req.params.id, function(err, result) {
res.render('location-detail', { title: 'Location Details', location: result, packages: packages });
});
};
Edit 1
The error I am getting is:
Cannot read property 'name' of undefined
My model looks like this:
var mongoose = require('mongoose')
,Schema = mongoose.Schema;
var PackageSchema = new mongoose.Schema({
name: String,
prev_package: String,
featured: Boolean,
services: Array
});
module.exports = mongoose.model('Package', PackageSchema);
And I am using this model in another view, and everything is working like a champ.
var mongoOp = require("./models/mongo");
var async = require('async');
router.get("/",function(req,res){
var locals = {};
var userId = req.params.userId;
async.parallel([
//Load user data using Mangoose Model
function(callback) {
mongoOp.User.find({},function(err,user){
if (err) return callback(err);
locals.user = user;
callback();
});
},
//Load posts data using Mangoose Model
function(callback) {
mongoOp.Post.find({},function(err,posts){
if (err) return callback(err);
locals.posts = posts;
callback();
});
}
], function(err) { //This function gets called after the two tasks have called their "task callbacks"
if (err) return next(err); //If an error occurred, we let express handle it by calling the `next` function
//Here `locals` will be an object with `user` and `posts` keys
//Example: `locals = {user: ..., posts: [...]}`
res.render('index.ejs', {quotes: locals.user,userdata: locals.posts})
});
});
So, it looks like this was another asynchronous "gotcha". Putting this into a nested callback did the trick:
exports.locationdetail = function(req, res) {
Location.findById(req.params.id, function(err, result) {
Package.find(function (err, results) {
res.render('location-detail', { title: 'Location Details', location: result, packages: results });
});
});
};

Resources