.save is not a function, and .findOneAndUpdate() doesn't update my db - javascript

I'm setting up a backend server, and i want to do a put method in router.
I'm using mongoose express in backend.
When i'm trying update some data in my db with .save() , i get error:
events.js:174
throw er; // Unhandled 'error' event
^
TypeError: PC.save is not a function
I'm trying another soulution with .findOneAndUpdate(), it is success but it doesn't update my database.
const express = require('express')
const routes = express()
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myapp', { useNewUrlParser: true });
const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error"));
db.once("open", function(callback){
console.log("Connection Succeeded");
});
var PC = require("../models/PC");
//...here is my get delete etc..
This is my first solution with findOneAndUpdate
routes.put('/:id', (req, res) => {
mongoose.set('useFindAndModify', false);
PC.findOneAndUpdate(
{ 'title': req.body.title },
{ '$set': {'description': req.body.description} },
{'new': true },
function(err, PC) {
if (err) {
console.log('ERROR WHILE PUT PC');
throw (err);
} else {
console.log('Succes set');
res.status(200).send(PC)
}
}
);
})
And this is my second solution
routes.put('/:id', (req, res) => {
PC.findById(req.params.id, 'title description', function (error, pc) {
if (error) { console.error(error); }
PC.title = req.body.title
PC.description = req.body.description
console.log(PC);
PC.save(function (error) {
if (error) {
console.log(error)
}
res.send({
success: true,
message: 'PC saved successfully!',
PC: req.body
})
})
})
})
module.exports = routes;
my model:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var PCSchema = new Schema({
id: Number,
brand: String,
cpu: String,
memory: Number,
type: String,
vga: String,
score: Number,
title: String,
description: String
});
var PC = mongoose.model("PC", PCSchema);
module.exports = PC;

In your first example it looks like you are finding with the wrong param, and you should be using id.
Try using findByIdAndUpdate instead:
routes.put('/:id', (req, res) => {
mongoose.set('useFindAndModify', false);
PC.findByIdAndUpdate(
req.params.id,
{ '$set': {'description': req.body.description, 'title': req.body.title} },
{'new': true },
function(err, pc) {
if (err) {
console.log('ERROR WHILE PUT PC');
throw (err);
} else {
console.log('Succes set');
res.status(200).send(pc)
}
}
);
})
In you second example, you should be calling .save on the result, not the original PC Model. You could change that to:
routes.put('/:id', (req, res) => {
PC.findById(req.params.id, 'title description', function (error, pc) {
if (error) { console.error(error); }
// Use lowercase `pc` on all these lines
pc.title = req.body.title
pc.description = req.body.description
console.log(pc);
pc.save(function (error) {
if (error) {
console.log(error)
}
res.send({
success: true,
message: 'PC saved successfully!',
PC: req.body
})
})
})
})

Related

How to fix: Error: data and hash arguments required

This is a rest API that fetches movie data, similar to Netflix. I've created a login route for new users and registered users, however, when I test the API on postman and attempt to log in as a user I get an error message:
Errors:
Expect Output:
I want the user to log in successfully
The Problem:
I can't find anything wrong with the code despite reference errors
Question:
What kind of data and hash arguments do I require? What is causing the problem?
Code:
source code
model.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
let movieSchema = mongoose.Schema({
Title: {
type: String,
required: true
},
Description: {
type: String,
required: true
},
Genre: {
Name: String,
Description: String
},
Director: {
Name: String,
Bio: String,
Birth: String
},
Actors: [String],
ImageURL: String,
Featured: Boolean
});
let userSchema = mongoose.Schema({
Username: {
type: String,
required: true
},
Password: {
type: String,
required: true
},
Email: {
type: String,
required: true
},
Birthday: Date,
FavoriteMovies: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Movie'
}]
});
// HASH THE PASSWORD BEFORE SAVING THE USER MODEL TO THE DATABASE
userSchema.statics.hashPassword = (password) => {
return bcrypt.hashSync(password, 10);
};
// COMPARE THE HASHED PASSWORD IN THE DATABASE WITH THE ONE PROVIDED BY THE USER WHEN THEY LOG IN
userSchema.methods.validatePassword = function(password) {
return bcrypt.compareSync(password, this.Password);
};
// SCHEMA FOR DIRECTORS
let directorSchema = mongoose.Schema({
Name: {
type: String,
required: true
},
Bio: {
type: String,
required: true
},
Birth: {
type: String,
required: true
}
})
/// SCHEMA FOR GENRES
let genreSchema = mongoose.Schema({
Name: {
type: String,
required: true
},
Description: {
type: String,
required: true
}
})
// CREATE MODELS FROM SCHEMAS
let Movie = mongoose.model('Movie', movieSchema);
let User = mongoose.model('User', userSchema);
let Director = mongoose.model('Director', directorSchema);
let Genre = mongoose.model('Genre', genreSchema);
// EXPORT MODELS
module.exports.Movie = Movie;
module.exports.User = User;
module.exports.Director = Director;
module.exports.Genre = Genre;
passport.js
const passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
Models = require('./models/models'),
passportJWT = require('passport-jwt');
let Users = Models.User,
JWTStrategy = passportJWT.Strategy,
ExtractJWT = passportJWT.ExtractJwt;
passport.use(new LocalStrategy({
usernameField: 'Username',
passwordField: 'Password'
}, (username, password, callback) => {
console.log(`${username} ${password}`);
Users.findOne({
Username: username
}, (error, user) => {
if (error) {
console.log(error);
return callback(error);
}
if (!user) {
console.log('incorrect username');
return callback(null, false, {
message: 'Incorrect username or password.'
});
}
if (!user.validatePassword(password)) {
console.log('incorrect password');
return callback(null, false, {
message: 'Incorrect password.'
});
}
console.log('finished');
return callback(null, user);
});
}));
passport.use(new JWTStrategy({
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: 'your_jwt_secret'
}, async(jwtPayload, callback) => {
try {
const user = await Users.findById(jwtPayload._id);
return callback(null, user);
} catch (error) {
return callback(error);
}
}));
index.js
const express = require('express'),
morgan = require('morgan'),
bodyParser = require('body-parser'),
uuid = require('uuid'),
mongoose = require('mongoose'),
Models = require('./models/models'),
{
check,
validationResult
} = require('express-validator');
const app = express();
// SCHEMAS
const Movies = Models.Movie;
const Users = Models.User;
const Genres = Models.Genre;
const Directors = Models.Director;
mongoose.connect('mongodb://localhost:27017/myMovies', {
useNewUrlParser: true,
useUnifiedTopology: true
}); // DATABASE Option 1: Local DB
// mongoose.connect(process.env.CONNECTION_URI, { useNewUrlParser: true, dbName: "myMoviesDB", useUnifiedTopology: true }); // REMOTE DATABASE Option 2: Remote DB
// MIDDLEWARE
app.use(bodyParser.json());
// LOGGING MIDDLEWARE
const cors = require('cors');
// ALL ORIGINS ARE ALLOWED TO ACCESS THE API ENDPOINTS
app.use(cors());
// CETAIN ORIGINS ARE ALLOWED TO ACCESS THE API ENDPOINTS:
// let allowedOrigins = ['http://localhost:8080', 'http://testsite.com']
// app.use(cors({
// origin: (origin, callback) => {
// if (!origin) return callback(null, true); // i don't understand this line
// if (allowedOrigins.indexOf(origin) === -1){ // specific origin not in allowedOrigins list
// let message = 'The CORS policy for this application doesn’t allow access from origin ' + origin;
// return callback(new Error(message), false);
// }
// return callback(null, true);
// }
// }));
// ERROR HANDLING MIDDLEWARE
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// INPUT VALIDATION
const userValidation = [
check('Username', 'Username is required').isLength({
min: 5
}),
check('Username', 'Username contains non alphanumeric characters - not allowed.').isAlphanumeric(),
check('Password', 'Password is required').not().isEmpty(),
check('Email', 'Email does not appear to be valid').isEmail()
];
// INPUT VALIDATION FOR MOVIES
const movieValidation = [
check('Title', 'Title is required').not().isEmpty(),
check('Description', 'Description is required').not().isEmpty(),
check('Genre', 'Genre is required').not().isEmpty(),
check('Director', 'Director is required').not().isEmpty(),
check('Actors', 'Actors is required').not().isEmpty(),
check('ImageURL', 'ImageURL is required').not().isEmpty(),
check('Featured', 'Featured is required').not().isEmpty()
];
//AUTHENTICATION
require('./auth')(app);
const passport = require('passport');
const {
Passport
} = require('passport');
require('./passport');
// LOGS REQUESTS TO THE CONSOLE
app.use(morgan('common'));
app.use(express.static('public'));
//ROUTING / HOME
app.get("/", (req, res) => {
res.send('Hello there! Welcome to myMovies');
})
// LIST OF ALL MOVIES
app.get('/users', passport.authenticate('jwt', {
session: false
}), (req, res) => {
Users.find()
.then((allUsers) => {
res.status(201).json(allUsers);
})
.catch((err) => {
console.error(err);
res.status(500).send(`Error: ${err}`);
});
});
// ADD User
app.post('/users', userValidation, (req, res) => {
//check for validation errors
let errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({
errors: errors.array()
});
}
let hashedPassword = Users.hashPassword(req.body.Password);
Users.findOne({
Username: req.body.Username
})
.then((user) => {
if (user) {
return res.status(400).send(`Username ${req.body.Username} already taken.`);
} else {
Users
.create({
Username: req.body.Username,
Password: hashedPassword,
Email: req.body.Email,
Birthday: req.body.Birthday
})
.then((new_user) => {
res.status(201).json(new_user)
})
.catch((error) => {
console.error(error);
res.status(500).send(`Error: ${error}`);
})
}
})
.catch((error) => {
console.error(error);
res.status(500).send(`Error: ${error}`);
});
});
// REMOVE USER
app.delete('/users/:Username', passport.authenticate('jwt', {
session: false
}), (req, res) => {
// ONLY ALLOWS USERS TO DELETE THEIR OWN ACCOUNT
if (req.user.Username !== req.params.Username) {
res.status(403).json('You are not authorized to delete this user.');
} else {
Users.findOneAndRemove({
Username: req.params.Username
})
.then((user) => {
if (!user) {
res.status(400).send(`${req.params.Username} was not found!`);
} else {
res.status(200).send(`${req.params.Username} was deleted`);
}
}).catch((err) => {
console.error(err);
res.status(500).send(`Error: ${err}`);
});
}
});
// GET USER INFO BY USERNAME
app.get('/users/:Username', passport.authenticate('jwt', {
session: false
}), (req, res) => {
Users.findOne({
Username: req.params.Username
}).then((user) => {
res.json(user);
}).catch((err) => {
console.error(err);
res.status(500).send(`Error: ${err}`);
});
});
// UPDATE USER INFO
app.put('/users/:Username', passport.authenticate('jwt', {
session: false
}), userValidation, (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({
errors: errors.array()
});
}
Users.findOneAndUpdate({
Username: req.params.Username
}, {
$set: {
Username: req.body.Username,
Password: req.body.Password,
Email: req.body.Email,
Birthday: req.body.Birthday
}
}, {
new: true
}, // This line ensures that the updated document is returned
(err, updateUser) => {
if (err) {
console.error(err);
res.status(500).send(`Error: ${err}`);
} else {
res.json(updateUser); // Return the updated document
}
})
});
// MOVIES
// GET: fetches a list of all movies
// app.get('/movies', (req, res) => {
// Movies.find()
// .then((movies) => {
// res.status(201).json(movies);
// })
// .catch((error) => {
// console.error(error);
// res.status(500).send(`Error: ${error}`);
// });
// });
app.get('/movies', passport.authenticate('jwt', {
session: false
}), (req, res) => {
Movies.find()
.then((movies) => {
res.status(201).json(movies);
})
.catch((error) => {
console.error(error);
res.status(500).send(`Error: ${error}`);
});
});
// GET: fetches movies by title
app.get('/movies/:Title', passport.authenticate('jwt', {
sesson: false
}), (req, res) => {
Movies.findOne({
Title: req.params.Title
})
.then((movie) => {
res.json(movie);
}).catch((err) => {
console.error(err);
res.status(500).send('Error: ' + err);
});
});
// ADD MOVIE TO FAVORITES LIST OF USER
app.post('/users/:Username/movies/:MovieID',
passport.authenticate({
session: false
}),
(req, res) => {
if (req.user.Username !== req.params.Username) {
res.status(403).json('Not allowed to add movie to another user\'s favorites list');
} else {
Users.findOneAndUpdate({
Username: req.params.Username
}, {
$addToSet: {
FavoriteMovies: req.params.MovieID
}
}, {
$push: {
FavoriteMovies: req.params.MovieID
}
}, {
new: true
}, // This line ensures that the updated document is returned
(err, updated_User) => {
if (err) {
console.error(err);
res.status(500).send(`Error:${err}`)
} else {
res.json(updated_User)
}
});
}
});
// REMOVE MOVIE FROM FAVORITES
app.delete('/users/:Username/movies/:MovieID', passport.authenticate('jwt', {
session: false
}), (req, res) => {
// ONLY ALLOQWS USERS TO REMOVE MOVIES FROM THEIR OWN FAVORITES
if (req.user.Username != req.params.Username) {
res.status(403).json('Not allowed to remove movie from another user\'s favorites list');
} else {
Users.findOneAndUpdate({
Username: req.params.Username
}, {
pull: {
FavoriteMovies: req.params.MovieID
}
}, {
new: true
}) // THIS LINE ENSURES THAT THE UPDATED DOCUMENT IS RETURNED
.then((updatedUser) => {
res.status(200).send(`Favorite movie removed from ${updatedUser.Username}`);
})
.catch((err) => {
console.error(err);
res.status(500).send(`Error: ${err}`);
});
}
});
// DIRECTORS
// RETURN A LIST OF ALL DIRECTORS BY NAME (BIO, BIRTHYEAR)
app.get('/directors/:Name', passport.authenticate('jwt', {
session: false
}), (req, res) => {
Directors.findOne({
Name: req.params.Name
}).then((director) => {
res.json(director);
}).catch((err) => {
console.error(err);
res.status(500).send('Error: ' + err); // 500: INTERNAL SERVER ERROR
})
})
// GENRES
// GET: returns all genres
app.get('/genres', (req, res) => {
Genres.find().then((genre) => {
res.status(201).json(genre);
}).catch((err) => {
console.error(err);
res.status(400).send('Error: ' + err);
})
})
// RETURNS GENRE BY NAME
app.get('/genres/:Name', (req, res) => {
Genres.findOne({
Name: req.params.Name
}).then((genreName) => {
res.status(201).json(genreName)
}).catch((err) => {
console.error(err);
res.status(500).send('Error: ' + err);
})
})
// DOCUMENTATION ROUTE
app.get('/documentation', (req, res) => {
res.sendFile('public/documentation.html');
});
// SERVER & HEROKU
const port = process.env.PORT || 8081;
app.listen(port, '0.0.0.0', () => {
console.log(`Listening on Port ${port}`);
});
Research:
I've searched and read through most of the common questions related to the issue, but none helped.
Question #1
Question #2
Thank you in advance for taking the time to answer my question.

Route.post() requires a callback function but got a [object Undefined]? Why am I getting this error?

I'm working on the backend of my react project and I seem to be having some trouble with the backend for the info. When I do npm start I get an error saying Route.post() requires a callback function but got a [object Undefined] and I'm confused as to why.
Here is my server.js file
const express = require("express");
const cors = require("cors");
const dbConfig = require("./app/config/db.config");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
const db = require("./app/models");
const Role = db.role;
db.mongoose
.connect(`mongodb+srv://tami00:MEUxClWqUNbLz359#cluster0.gmvao.mongodb.net/test?retryWrites=true&w=majority`, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Successfully connect to MongoDB.");
initial();
})
.catch(err => {
console.error("Connection error", err);
process.exit();
});
// simple route
app.use('/favourite', require('.app/routes/favourite.routes'));
// routes
// require(".app/routes/favourite.routes")(app);
require("./app/routes/auth.routes")(app);
require("./app/routes/user.routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
function initial() {
Role.estimatedDocumentCount((err, count) => {
if (!err && count === 0) {
new Role({
name: "user"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'user' to roles collection");
});
new Role({
name: "creator"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'creator' to roles collection");
});
new Role({
name: "watcher"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'watcher' to roles collection");
});
}
});
}
and here is my favourite.routes.js file. I have no issue with the other 2 routes.
const express = require('express');
const router = express.Router();
const{Favourite} = require("../models/favourite.model");
const {auth} = require("../middlewares/authJwt");
router.post("/favouriteNumber", auth, (req, res) => {
Favourite.find({"movieId": req.body.movieId})
.exec((err, favourite) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, favouriteNumber: favourite.length})
})
})
router.post("/favourited", auth, (req, res) => {
Favourite.find({"movieId": req.body.movieId, "userFrom": req.body.userFrom})
.exec((err, favourite) => {
if(err) return res.status(400).send(err)
let result = false;
if(favourite.length !== 0) {
result = true
}
res.status(200).json({success: true, favourited: result});
})
})
router.post("/addToFavourite", auth, (req, res) => {
const favourite = new Favourite(req.body)
favourite.save((err, doc) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, doc})
})
})
router.post("/removeFavorite", auth, (req, res) => {
Favourite.findOneAndDelete({movieId: req.body.movieId, userFrom: req.body.userFrom})
.exec((err, doc) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, doc})
})
})
module.exports = router;
This is the favourite models where I'm creating the mongoose schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const favSchema = mongoose.Schema({
userFrom: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
movieId : {
type: String
},
movieTitle : {
type: String
},
movieImg : {
type: String
}
})
const Favourite = mongoose.model('Favourite', favSchema);
module.exports = {Favourite}
Heres the middlewares auth file
const jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
const db = require("../models");
const User = db.user;
const Role = db.role;
verifyToken = (req, res, next) => {
let token = req.headers["x-access-token"];
if (!token) {
return res.status(403).send({ message: "No token provided!" });
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.status(401).send({ message: "Unauthorized!" });
}
req.userId = decoded.id;
next();
});
};
isAdmin = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "admin") {
next();
return;
}
}
res.status(403).send({ message: "Require Admin Role!" });
return;
}
);
});
};
isModerator = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles }
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "moderator") {
next();
return;
}
}
res.status(403).send({ message: "Require Moderator Role!" });
return;
}
);
});
};
const authJwt = {
verifyToken,
isAdmin,
isModerator
};
module.exports = authJwt;
const {auth} = require("../middlewares/authJwt"); uses destructuring, but your exports from ../middlewares/authJwt don't have a field auth.
auth therefore is undefined.

I am getting this.parent.acquire error in mssql Node JS

I am getting (this.parent.acquire is not a function) error in the following code
app.post("/add", (req,res) => {
const config = {
server: 'server', //update me
user: 'user', //update me
password: 'pass', //update me
database: 'db',
trustServerCertificate: true
}
let pool2 = sql.connect(config)
try {
const transaction = new sql.Transaction(pool2)
transaction.begin(err => {
if(err) {
console.log(err);
}
const request = new sql.Request(transaction)
request.query('insert into fsraSample (A93) values (12345)', (err, result) => {
if(err) {
console.log(err);
}
transaction.commit(err => {
if(err) {
console.log(err);
}
console.log("Transaction committed.")
})
})
})
} catch(err) {
console.log();
}
res.sendFile(path.join(__dirname + '/index.html'));
});
Whats the issue here? I am using the above code to insert some data in sql server using node js

mochajs & chaijs - Uncaught TypeError: Cannot read property 'id' of undefined

I am creating an bill tracking application that is having users create bills based on criteria I have created using javascript.
I am tasked with performing acceptance testing.
This is my code so far:
My index.js file
const express = require('express')
const app = express()
const port = 3000
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bill');
var MongoClient = require('mongodb').MongoClient
var ObjectID = require('mongodb').ObjectID
app.use(express.json())
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'))
app.set('view engine', 'pug')
app.set('views', __dirname + '/views');
var billSchema = new mongoose.Schema(
{
type: { type: String, required: true },
dueDate: { type: Date, required: true },
company: { type: String, required: true },
amtDue: { type: Number, required: true },
paidStatus: { type: String, required: true }
});
var bill = mongoose.model('bill', billSchema);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function()
{
app.get('/', (req, res) =>
{
bill.find({}, function(err, bills)
{
if (err)
{
console.log(err)
res.render('error', {})
}
else
{
res.render('index', { bills: bills })
}
});
});
app.get('/bills/new', (req, res) =>
{
res.render('bill-form', { title: "New bill", bill: {} })
});
app.get('/bills/:id/update', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.findById(id, function(err, bill)
{
if (err)
{
console.log(err)
res.render('error', {})
}
else
{
if (bill === null) {
res.render('error', { message: "Not found" })
} else {
res.render('bill-form', { title: "Update bill", bill: bill })
}
}
});
});
app.post('/bills/new', function(req, res, next) {
let newbill = new bill(req.body);
newbill.save(function(err, savedbill)
{
if (err)
{
console.log(err)
res.render('bill-form', { bill: newbill, error: err })
}
else
{
res.redirect('/bills/' + savedbill.id);
}
});
});
app.get('/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.findById(id, function(err, bill)
{
if (err)
{
console.log(err)
res.render('error', {})
}
else
{
if (bill === null)
{
res.render('error', { message: "Not found" })
}
else
{
res.render('bill-detail', { bill: bill})
}
}
});
});
app.post('/bills/:id/update', (req, res, next) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.updateOne({"_id": id}, { $set: req.body }, function(err, details)
{
if(err)
{
console.log(err)
res.render('error', {})
}
else
{
res.redirect('/bills/' + id)
}
});
});
app.post('/bills/:id/delete', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.deleteOne({_id: id}, function(err, product)
{
res.redirect("/")
});
});
app.post('/api/bills', (req, res) =>
{
let newbill = new bill(req.body)
newbill.save(function (err, savedbill)
{
if (err)
{
console.log(err)
res.status(500).send("There was an internal error")
}
else
{
res.send(savedbill)
}
});
});
app.post('/api/bills', (req, res) =>
{
bill.find({}, function(err, bills)
{
if(err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.send(bills)
}
});
});
app.get('/api/bills', (req, res) =>
{
bill.find({}, function(err, bills)
{
if(err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.send(bills)
}
});
});
app.get('/api/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.findById(id, function(err, bill)
{
if (err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
if (bill === null)
{
res.status(404).send("Not found")
}
else
{
res.send(bill)
}
}
});
});
app.put('/api/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
bill.updateOne({"_id": id}, { $set: req.body }, function(err, details)
{
if (err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.status(204).send()
}
});
});
app.delete('/api/bills/:id', (req, res) =>
{
let id = ObjectID.createFromHexString(req.params.id)
Review.deleteOne({"_id": id}, function(err)
{
if (err)
{
console.log(err)
res.status(500).send("Internal server error")
}
else
{
res.status(204).send()
}
});
});
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
module.exports.app = app;
module.exports.schema = bill;
Then I have a javscript dedicated to testing
let assert = require('assert');
let chai = require('chai');
let chaiHttp = require('chai-http');
let serverAndSchema = require('../index');
let server = serverAndSchema.app
let Bill = serverAndSchema.schema
let should = chai.should();
chai.use(chaiHttp);
describe('Bills', function() {
describe('/GET bill', function() {
it('should get the specified bill', function(done) {
let expectedBill = new Bill({
type: "Test Type",
dueDate: "12/3/2018T06:00:00.000Z",
company: "Test Company",
amtDue: "100",
paidStatus: "Test Status"
});
expectedBill.save(function(err, savedBill) {
chai.request(server)
.get('/api/bills/'+savedBill.id)
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a('object');
res.body.should.have.property('type').eql(savedBill.type)
res.body.should.have.property('dueDate').eql(savedBill.dueDate)
res.body.should.have.property('company').eql(savedBill.company)
res.body.should.have.property('amtDue').eql(savedBill.amtDue)
res.body.should.have.property('paidStatus').eql(savedBill.paidStatus)
res.body.should.have.property('_id').eql(savedBill.id)
done();
})
});
});
});
});
The data is added to my database, but I get this error when I try to run the test:
Uncaught TypeError: Cannot read property 'id' of undefined
at
C:\Users\Martae\Documents\Github\BillTracker\test\bill.js:29:46
Any help with this is appreciated!
When I checked the Bill schema, I found that the issue is caused by your due date format. So, the mongo saved is failed and you got undefined for savedBill and when you try to access id, it throws the error that you got.
Here is the solution:
let expectedBill = new Bill({
type: "Test Type",
dueDate: "2018-03-13T06:00:00.000Z", // change date to standardized format
company: "Test Company",
amtDue: "100",
paidStatus: "Test Status"
});
expectedBill.save(function(err, savedBill) {
const id = savedBill._id; // store id, it is always returned as _id
chai.request(server)
.get('/api/bills/'+id)
.end((err, res) => {
// ...
done();
});
});

How can you remove all documents from a collection with Mongoose?

I know how to...
Remove a single document.
Remove the collection itself.
Remove all documents from the collection with Mongo.
But I don't know how to remove all documents from the collection with Mongoose. I want to do this when the user clicks a button. I assume that I need to send an AJAX request to some endpoint and have the endpoint do the removal, but I don't know how to handle the removal at the endpoint.
In my example, I have a Datetime collection, and I want to remove all of the documents when the user clicks a button.
api/datetime/index.js
'use strict';
var express = require('express');
var controller = require('./datetime.controller');
var router = express.Router();
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
module.exports = router;
api/datetime/datetime.controller.js
'use strict';
var _ = require('lodash');
var Datetime = require('./datetime.model');
// Get list of datetimes
exports.index = function(req, res) {
Datetime.find(function (err, datetimes) {
if(err) { return handleError(res, err); }
return res.json(200, datetimes);
});
};
// Get a single datetime
exports.show = function(req, res) {
Datetime.findById(req.params.id, function (err, datetime) {
if(err) { return handleError(res, err); }
if(!datetime) { return res.send(404); }
return res.json(datetime);
});
};
// Creates a new datetime in the DB.
exports.create = function(req, res) {
Datetime.create(req.body, function(err, datetime) {
if(err) { return handleError(res, err); }
return res.json(201, datetime);
});
};
// Updates an existing datetime in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Datetime.findById(req.params.id, function (err, datetime) {
if (err) { return handleError(res, err); }
if(!datetime) { return res.send(404); }
var updated = _.merge(datetime, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, datetime);
});
});
};
// Deletes a datetime from the DB.
exports.destroy = function(req, res) {
Datetime.findById(req.params.id, function (err, datetime) {
if(err) { return handleError(res, err); }
if(!datetime) { return res.send(404); }
datetime.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(204);
});
});
};
function handleError(res, err) {
return res.send(500, err);
}
DateTime.remove({}, callback) The empty object will match all of them.
.remove() is deprecated. instead we can use deleteMany
DateTime.deleteMany({}, callback).
In MongoDB, the db.collection.remove() method removes documents from a collection. You can remove all documents from a collection, remove all documents that match a condition, or limit the operation to remove just a single document.
Source: Mongodb.
If you are using mongo sheel, just do:
db.Datetime.remove({})
In your case, you need:
You didn't show me the delete button, so this button is just an example:
<a class="button__delete"></a>
Change the controller to:
exports.destroy = function(req, res, next) {
Datetime.remove({}, function(err) {
if (err) {
console.log(err)
} else {
res.end('success');
}
}
);
};
Insert this ajax delete method in your client js file:
$(document).ready(function(){
$('.button__delete').click(function() {
var dataId = $(this).attr('data-id');
if (confirm("are u sure?")) {
$.ajax({
type: 'DELETE',
url: '/',
success: function(response) {
if (response == 'error') {
console.log('Err!');
}
else {
alert('Success');
location.reload();
}
}
});
} else {
alert('Canceled!');
}
});
});
MongoDB shell version v4.2.6
Node v14.2.0
Assuming you have a Tour Model: tourModel.js
const mongoose = require('mongoose');
const tourSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'A tour must have a name'],
unique: true,
trim: true,
},
createdAt: {
type: Date,
default: Date.now(),
},
});
const Tour = mongoose.model('Tour', tourSchema);
module.exports = Tour;
Now you want to delete all tours at once from your MongoDB, I also providing connection code to connect with the remote cluster.
I used deleteMany(), if you do not pass any args to deleteMany(), then it will delete all the documents in Tour collection.
const mongoose = require('mongoose');
const Tour = require('./../../models/tourModel');
const conStr = 'mongodb+srv://lord:<PASSWORD>#cluster0-eeev8.mongodb.net/tour-guide?retryWrites=true&w=majority';
const DB = conStr.replace('<PASSWORD>','ADUSsaZEKESKZX');
mongoose.connect(DB, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
})
.then((con) => {
console.log(`DB connection successful ${con.path}`);
});
const deleteAllData = async () => {
try {
await Tour.deleteMany();
console.log('All Data successfully deleted');
} catch (err) {
console.log(err);
}
};
Your_Mongoose_Model.deleteMany({}) can do the job
References:
https://mongoosejs.com/docs/api.html#query_Query-deleteMany
https://www.geeksforgeeks.org/mongoose-deletemany-function/

Categories

Resources