find function is not working in mongoose with specified field - javascript

So I am making this website where you can see different recipes for food. When browsing for recipes, I want the user to be able to select a category and browse all the dishes that fall under it (i.e dessert, dinner, vegan etc).
I have this function I created in my router file that returns all the dishes that fall under the specified category:
router.get('/showrecipes/:categoryname', (req, res, next) => {
let nameQuery = {category: req.params.categoryname};
Recipe.find(nameQuery, (err, recipes) => {
if (err) throw err;
res.json(recipes);
});
});
However, when I try to test it out in Postman, I keep getting Null instead of all the dishes that fall under the category.
All my other functions are correctly working, but this one seems to have issues.
For reference, here is the rest of the recipeRouter file:
const express = require('express');
const passport = require('passport');
const Recipe = require('../models/recipe');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
router = express.Router();
router.get('/', (req, res, next) => {
res.json('Here are the recipes!')
});
// Is working
router.get('/showrecipes', (req, res, next) => {
Recipe.find({}, (err, recipes) => {
if (err) throw err;
res.json(recipes);
});
});
// Is working.
router.get("/showrecipes/:recipename", (req, res, next) => {
let nameQuery = {name: req.params.recipename};
Recipe.findOne(nameQuery, (err, recipes) => {
if (err) throw err;
res.json(recipes);
})
});
// Is not crashing, but is returning Null which isn't how it's supposed to work.
router.get('/showrecipes/:categoryname', (req, res, next) => {
let nameQuery = {category: req.params.categoryname};
Recipe.find(nameQuery, (err, recipes) => {
if (err) throw err;
res.json(recipes);
});
});
// Now it's working, good stuff.
router.post('/addrecipe', (req, res, next) => {
Recipe.create({
name: req.body.name,
description: req.body.description,
steps: req.body.steps,
ingredients: req.body.ingredients,
category: req.body.category,
}, (err, recipe) => {
if (err) throw err;
// Recipe.save();
res.json(recipe);
});
});
// See if this works
router.put('editrecipe/:recipename/:editedField', (req, res, next) => {
Recipe.findOneAndUpdate({name: req.params.recipename}, {$set: req.body}, {new: true}, (err, recipe) => {
if (err) throw err;
res.json(recipe)
});
});
// It's working, thank god
router.delete('/deleterecipe/:recipename', (req, res, next) => {
let nameQuery = {name: req.params.recipename};
Recipe.findOneAndRemove(nameQuery, (err, recipe) => {
if (err) throw err;
res.send('Dish was succesfully deleted!')
});
});
module.exports = router;
And here is my app.js file
let express = require('express');
let mongoose = require('mongoose');
let path = require('path');
let bodyParser = require('body-parser');
let recipeRouter = require('./routes/recipeRouter');
let userRouter = require('./routes/userRouter');
let bcrypt = require('bcrypt');
let passport = require('passport');
let LocalStrategy = require('passport-local').Strategy;
let config = require('./config');
mongoose.connect(config.mongoUrl);
let db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
// we're connected!
console.log("Connected correctly to server");
});
const app = express();
const port = 3000;
app.listen(port);
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.set('views', path.join(__dirname, 'views'));
app.use('/users', userRouter);
app.use('/recipes',recipeRouter);
app.get('/', function(req, res){
res.send('Hey, this is your database!')
});
module.exports = app;
And here is my Recipe file
const express = require('express');
const mongoose = require('mongoose');
const User = require('../models/user');
let Schema = mongoose.Schema;
let commentSchema = Schema({
rating: {
type: Number,
required: true,
min: 1,
max: 5,
},
comment: {
type: String,
required: true
},
postedBy: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
let Comment = mongoose.model('Comment', commentSchema);
let recipeSchema = Schema({
name: {
type: String,
required: true
},
description: {
type: String,
},
steps: {
type: String,
required: true,
},
ingredients: {
type: Array,
required: true
},
comments: [commentSchema],
category: {
type: String,
required: true,
},
postedBy: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
/// So I learnt that by defining the string as "Recipe" in the model function, I will have to lower case it
/// and pluralize it when I use it with res.json and other such things (i.e. "Recipe" => recipes).
let Recipe = mongoose.model('Recipe', recipeSchema);
module.exports = Recipe;
/// refactor this so that these are in the router, not in the models file
/*
module.exports.getRecipeByName = (name, callback) => {
let nameQuery = {name: name};
Recipe.findOne(nameQuery, callback);
};
module.exports.getRecipesByCategory = (category, callback) => {
Recipe.find({'category': category});
};
*/

Related

Why am I keeping getting 'Collection is undefined' error on MongoDb

I tried to connect to my db but it keep on returning that the collection is undefined even though I already declared it as a global variable. Not really sure what the closure issue is.
const express = require('express');
const app = express();
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
let db;
MongoClient.connect('mongodb://localhost:27017/todos', { useUnifiedTopology: true }, (err, client) => {
assert.equal(nul, err);
db = client.db('todos');
db.collection('todos').insertMany([
{ done:true, desc: 'write code'},
{ done:true, desc: 'write code'},
{ done:true, desc: 'write code'},
]);
client.close();
})
app.get('/', (req, res) => {
res.json('did this work!');
});
app.get('/todos', async (req, res) => {
const todos = await db.collection('todos').find().toArray();
res.json(todos);
});
app.listen(3001, () =>{
console.log("work pls");
});

node.js req.body returning undefined

EDIT: #LawrenceCherone solved this, its (req, res, next) not (err, res, req)
I am creating a MERN app (Mongo, express, react, node).
I have some routes that work fine and return data from mongodb. However I created a new controller to access a separate collection and whenever i try to create a new document in it my req.body returns undefined.
I have setup my server.js like this:
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const connectDB = require("./db");
const app = express();
const apiPort = 3000;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors());
app.use(bodyParser.json());
connectDB();
app.use("/api", require("./routes/router"));
var server = app.listen(apiPort, () => console.log(`Server running on port ${apiPort}`));
module.exports = server;
My router looks like this:
const express = require("express");
const QuizController = require("../controllers/quiz-controller");
const UserController = require("../controllers/user-controller");
const router = express.Router();
// quiz routes
router.post("/quizzes", QuizController.createQuestion);
router.get("/quizzes", QuizController.getAllQuestions);
router.get("/quizzes/:quiz_name", QuizController.getQuestionsByQuiz);
router.get("/quizzes/questions/:question_id", QuizController.getQuestionById);
router.put("/quizzes/:question_id/edit", QuizController.updateQuestionById);
router.delete("/quizzes/:question_id", QuizController.deleteQuestionById);
// user routes
router.post("/users", UserController.createUser);
module.exports = router;
All of the /quizzes routes work perfectly fine and i have had no trouble accessing the body. The UserController.createUser method is almost identical to Quizcontroller.createQuestion too so I am very confused.
Here is the user-controller with the createUser function:
const User = require("../models/User");
createUser = async (err, res, req) => {
const body = req.body;
console.log(req.body);
console.log(req.params);
console.log(body);
if (!body) {
return res.status(400).json({
succes: false,
error: "You must provide a body",
});
}
try {
const newUser = new User(body);
console.log(newUser);
if (!newUser) {
return res.status(400).json({ success: false, error: err });
}
const user = await newUser.save();
return res
.status(200)
.json({ success: true, newUser: user, msg: "New user created" });
} catch (err) {
console.error(err.message);
res.status(500).send("Server error");
}
};
module.exports = { createUser };
Here is an image of the postman request I am using to try test this:
[1]: https://i.stack.imgur.com/UHAK5.png
And the user model:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
emailAddress: {
type: String,
required: true,
},
permission: {
type: String,
required: true,
},
auth0Id: {
type: String,
required: true,
},
});
module.exports = mongoose.model("users", UserSchema);
The functional parameter order matters.
its
createUser = async (req, res, next) => // correct format
Not
createUser = async (err, res, req) // wrong format

How to join collection in mongoose?

My problem is I want to join this schema. Eg: In any e-commerce website there is a main image and after clicking that product we can see multiple image of that product. For uploading image I use multer package and in multer we cant upload single image and array of image in the same form so I create a new form that only takes an array of images. So I want to join that array of image data with my main form
This schema is to upload a single image:
const mongoose = require('mongoose');
const singleImageSchema = new mongoose.Schema({
file: {
type: mongoose.Schema.Types.ObjectId,
ref: 'File',
},
singleImage: {
type: String,
},
});
module.exports = new mongoose.model('File', singleImageSchema);
This schema is to upload multiple images:
const mongoose = require('mongoose');
const multipleImageSchema = new mongoose.Schema({
multipleImage: {
type: [String],
},
});
module.exports = new mongoose.model('Image', multipleImageSchema);
const express = require('express');
const bodyParser = require('body-parser');
const ejs = require('ejs');
const mongoose = require('mongoose');
const multer = require('multer');
const path = require('path');
const helpers = require('./helpers');
const singleImage = require('./models/singleImage');
const multipleImage = require('./models/multipleImage');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads');
},
// By default, multer removes file extensions so let's add them back
filename: function (req, file, cb) {
cb(
null,
file.fieldname + '-' + Date.now() + path.extname(file.originalname),
);
},
});
const app = express();
app.set('view engine', 'ejs');
app.use(
bodyParser.urlencoded({
extended: true,
}),
);
app.use(express.static('public'));
//connect to database
mongoose.connect('mongodb://localhost:27017/ImageInDB', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
console.log('Database is connected successfully on port 27017!!!');
});
app.get('/', (req, res) => {
res.render('file_upload');
});
app.post('/upload-profile-pic', (req, res) => {
let upload = multer({
storage: storage,
fileFilter: helpers.imageFilter,
}).single('profile_pic');
upload(req, res, function (err) {
if (req.fileValidationError) {
return res.send(req.fileValidationError);
} else if (!req.file) {
return res.send('Please select an image to upload');
} else if (err instanceof multer.MulterError) {
return res.send(err);
} else if (err) {
return res.send(err);
}
const oneImage = new singleImage({
singleImage: req.file.filename,
});
oneImage.save(err => console.log(err));
// Display uploaded image for user validation
singleImage.find({}, (err, product) => {
res.render('preview', {
product: product,
});
});
});
});
app.post('/upload-multiple-images', (req, res) => {
let upload = multer({
storage: storage,
fileFilter: helpers.imageFilter,
}).array('multiple_images', 10);
upload(req, res, function (err) {
if (req.fileValidationError) {
return res.send(req.fileValidationError);
} else if (!req.files) {
return res.send('Please select an image to upload');
} else if (err instanceof multer.MulterError) {
return res.send(err);
} else if (err) {
return res.send(err);
} // The same as when uploading single images
const files = req.files;
const moreImage = new multipleImage({
multipleImage: files.map(file => file.filename),
});
moreImage.save(err => console.log(err));
// Loop through all the uploaded images and display them on frontend
multipleImage.find({}, (err, products) => {
res.render('multiPreview', {
products: products,
});
});
});
});
app.listen(3000, function () {
console.log('Server started on port 3000');
});
You need to add reference schema to singleImageSchema and then use populate() method like this:
const singleImageSchema = new mongoose.Schema({
file: {
type: mongoose.Schema.Types.ObjectId,
ref: 'File',
},
singleImage: {
type: String,
},
multipleImage: [{ type: Schema.Types.ObjectId, ref: 'Image' }]
});
then your query will become
singleImage
.find()
.populate('multipleImage')
.exec(function(err, result) {
});
Documentation for populate() method: https://mongoosejs.com/docs/populate.html
Instead why you are not adding in single table?

NodeJS & MongoDB. POST Request gets 404 code

When I am trying to send POST request, it returns 404, although all routes is right.
I've rummaged through tons of similar questions but I didn't find anything that seems to solve my problem.
Here's a code:
App.js
const http = require('http');
const url = require('url');
const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const bodyParser = require('body-parser');
const passport = require('passport');
mongoose.connect('mongodb://localhost:27017/mydb');
let db = mongoose.connection;
db.once('open', () => {
console.log('Connected to Database');
});
db.on('error', (err) => {
console.log(err);
});
const server = express();
server.use(express.static('dist', { extensions: ['html'] }));
let users = require('./routes/users');
server.use(users);
server.use(function (req, res, next) {
res.status(404).sendFile(path.join(__dirname+'/dist/404.html'));
});
const port = process.env.port || 3000;
server.listen(port, () => {
console.log(`Server has been established on port ${port}`)
});
./models/user.js
const User = mongoose.Schema({
name: {
type: String,
required: true
},
lastname: {
type: String,
required: true
},
login: {
type: String,
required: true
},
password: {
type: String,
required: true
},
b_day: {
type: String,
required: true
},
b_month: {
type: String,
required: true
},
b_year: {
type: String,
required: true
},
gender: {
type: String,
required: true
}
});
const user = module.exports = mongoose.model('User', User);
./routes/users.js
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
let User = require('../models/user');
//Register Form
router.get('/signup', (req, res) => {
console.log(res);
res.render('signup');
});
//Register Process
router.post('signup', (req, res) => {
const name = req.body.name;
const lastname = req.body.lastname;
const login = req.body.login;
const password = req.body.password;
const password2 = req.body.repeat_password;
const b_day = req.body.b_day;
const b_month = req.body.b_month;
const b_year = req.body.b_year;
const gender = req.body.gender;
req.checkBody('name', 'Name is required').notEmpty();
req.checkBody('lastname', 'Lastname is required').notEmpty();
req.checkBody('login', 'Login is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
req.checkBody('b_day', 'Birth day is required').notEmpty();
req.checkBody('b_month', 'Birth month is required').notEmpty();
req.checkBody('b_year', 'Birth year is required').notEmpty();
req.checkBody('gender', 'Gender is required').notEmpty();
let errors = req.validationErrors();
if(errors) {
res.render('signup', {
errors:errors
});
} else {
let newUser = new User({
name:name,
lastname:lastname,
login:login,
password:password,
gender:gender,
b_day:b_day,
b_month:b_month,
b_year:b_year
});
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err) {
console.log(err);
}
newUser.password = hash;
newUser.save((err) => {
if(err) {
console.log(err);
return;
} else {
req.flash('success', 'You are now registered');
res.redirect('signin');
}
});
});
});
}
});
router.get('signin', (req, res) => {
res.render('signin');
});
router.post('signin', (req, res, next) => {
passport.authenticate('local', {
successRedirect:'profile',
failureRedirect:'signin',
failureFlash: true
})(req, res, next);
});
router.get('logout', (req, res) => {
res.render('logout');
req.flash('success', 'You are logged out');
res.redirect('signin');
});
module.exports = router;
And also project structure
├── dist
├── routes
│ └── users.js
├── models
│ └── user.js
└── app.js
I expect it will process all data from sign up form and then redirect to sign in page.
Your routes are correct. Error 404 only comes if a route is not found. In your case, its happening because you have not added "/" before calling signup(post request) and signin routes as well in users.js.
Right now your api url is becoming like this :
localhost:3000/userssignin
which should be :
localhost:3000/users/signin
So, your routes should be :
router.post('/signup', (req, res) => {
router.get('/signin', (req, res) => {
router.post('/signin', (req, res) => {
i don't know, but from a first view, i think that you are missing dash before routes
router.get('signin', (req, res) => { // '/singin'
res.render('signin');
});
router.post('signin', (req, res, next) => { // '/singin'
passport.authenticate('local', {
successRedirect:'profile',
failureRedirect:'signin',
failureFlash: true
})(req, res, next);
});
router.get('logout', (req, res) => { // '/logout'
res.render('logout');
req.flash('success', 'You are logged out');
res.redirect('signin');
});

"TypeError: User is not a constructor " while sending object to server in node.js

I am trying to save a user to mongodb database using post request as follow, but I got the error TypeError: User is not a constructor. It's a pretty simple set up of the code but i can't figure out anything wrong with it.
//models/users.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const confic = require('../models/users');
// User schema
const UserSchema = mongoose.Schema({
name: {
type: String,
},
email: {
type: String,
required: true
},
username:{
type: String,
required: true
},
password: {
type: String,
required: true
}
});
const User = module.exports = mongoose.model('User', UserSchema);
module.exports.getUserById = function(id,callback){
User.findById(id,callback);
}
module.exports.getUserByUsername = function(username,callback){
const query = {username:username}
User.findOne(query,callback);
}
module.exports.addUser= function (newUser, callback) {
bcrypt.gensalt(10,(err,salt) => {
bcrypt.hash(newUser.password, salt , (err, hash) =>{
if(err) throw err;
newUser.password=hash;
newUser.save(callback);
});
});
}
routes/users.js
//routes/users.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
User = require('../models/users');
// // Register
router.post('/register', (req, res, next) => {
var newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, User) => {
if(err){
res.json({success: false, msg:'Failed to register user'});
} else {
res.json({success: true, msg:'User registered'});
}
});
});
// Authenticate
router.post('/authenticate', (req, res, next) => {
res.send('AUTHENTICATE');
});
// Profile
router.get('/profile', (req, res, next) => {
res.send('PROFILE');
});
module.exports = router;
I am using Postman chrome to send data but it is not showing user registered according to program.
You are exporting your user model from a different file and trying to import from a different file.
change this line:
const User = require('../config/database');
to this:
const User = require('../models/users') # import your user model

Categories

Resources