How to delete a doc with id with mongoose? - node.js

I want to delete a doc with id in mongoose. It executes the method but doesn't delete that doc in MongoDB Altas.
Note:Everthing is correct and also Passing id correctly in PostMan.
here is my controller :
const Post = require("../models/Post");
const mongoose = require("mongoose");
exports.postPost = async (req, res) => {
try {
const post = await new Post({
_id: new mongoose.Types.ObjectId(),
title: req.body.title,
desc: req.body.desc,
}).save();
console.log("Saved in db!");
return res.status(201).json({
success: true,
data: post,
});
} catch (error) {
return res.status(500).json({
success: false,
message: "Server Error",
});
}
};
exports.deletePost = async (req, res) => {
let postID = req.params.id;
await Post.deleteOne({ _id: postID }, (err, data) => {
if (err) {
res.status(500).json({
message: "Something went wrong, please try again later.",
});
} else {
res.status(200).json({
message: "Post Deleted",
data: data,
});
}
});
};
here is my posts route:
const express = require("express");
const router = express.Router();
const {
postPost,
deletePost,
} = require("../controllers/posts_controller");
router.route("/:id").delete(deletePost);
router.route("/").post(postPost);
module.exports = router;
here is my postman :
here is my mongodb altas:

use the findOneAndDelete({_id:postId}) instead of deleteOne in posts controller
Or
use findByIdAndDelete(postId) instead of deleteOne in posts controller

exports.deletePost = async (req, res) => {
let postID = req.params.id;
await Post.findByIdAndDelete(postID, (err, data) => {
if (err) {
res.status(500).json({
message: "Something went wrong, please try again later.",
});
} else {
res.status(200).json({
message: "Post Deleted",
data: data,
});
}
});
};

Related

Uncaught TypeError: Cannot read properties of undefined (reading 'reviews')

I'm pretty new to react, and I working on a product where I am trying to get the number of individual ratings of a product from the total number of reviews. This is in my front end in my productScreen.js:
const getNumRating = (num) => product.reviews.filter((x) => x.rating === num).length;
The problem that I'm having is that every once in awhile I'm get a Uncaught TypeError: Cannot read properties of undefined (reading 'reviews') error on this line. Reviews comes from reviews: [reviewSchema] in my productModel.js.
I'm unsure as to why I'm getting this. In the return (); portion of my productScreen.js document, I have:{product.reviews.map((review) => (... ))}, which works fine.
Could I not be passing reviews from my backend to my fronted?
This is my ProductRouter.js document:
import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import data from '../data.js';
import Product from '../models/productModel.js';
import { isAdmin, isAuth, isSellerOrAdmin } from '../utils.js';
const productRouter = express.Router();
productRouter.get(
'/seed',
expressAsyncHandler(async (req, res) => {
// await Product.remove({});
const createdProducts = await Product.insertMany(data.products);
res.send({ createdProducts });
})
);
productRouter.get(
'/:id',
expressAsyncHandler(async (req, res) => {
const product = await Product.findById(req.params.id);
if (product) {
res.send(product);
} else {
res.status(404).send({ message: 'Product Not Found' });
}
})
);
productRouter.post(
'/',
isAuth,
isSellerOrAdmin,
expressAsyncHandler(async (req, res) => {
const product = new Product({
name: 'sample name ' + Date.now(),
});
const createdProduct = await product.save();
res.send({ message: 'Product Created', product: createdProduct });
})
);
productRouter.put(
'/:id',
isAuth,
isSellerOrAdmin,
expressAsyncHandler(async (req, res) => {
const productId = req.params.id;
const product = await Product.findById(productId);
if (product) {
product.name = req.body.name;
const updatedProduct = await product.save();
res.send({ message: 'Product Updated', product: updatedProduct });
} else {
res.status(404).send({ message: 'Product Not Found' });
}
})
);
productRouter.delete(
'/:id',
isAuth,
isAdmin,
expressAsyncHandler(async (req, res) => {
const product = await Product.findById(req.params.id);
if (product) {
const deleteProduct = await product.remove();
res.send({ message: 'Product Deleted', product: deleteProduct });
} else {
res.status(404).send({ message: 'Product Not Found' });
}
})
);
productRouter.post(
'/:id/reviews',
isAuth,
expressAsyncHandler(async (req, res) => {
const productId = req.params.id;
const product = await Product.findById(productId);
if (product) {
if (product.reviews.find((x) => x.name === req.user.name)) {
return res
.status(400)
.send({ message: 'You already submitted a review' });
}
const review = {
name: req.user.name,
rating: Number(req.body.rating),
comment_title: req.body.comment_title,
comment: req.body.comment,
age: req.body.age,
customerImages: req.body.customerImages,
};
product.reviews.push(review);
product.numReviews = product.reviews.length;
product.rating =
product.reviews.reduce((a, c) => a = a +c.rating, 0) /
product.reviews.length;
const updatedProduct = await product.save();
res.status(201).send({
message: 'Review Created',
review: updatedProduct.reviews[updatedProduct.reviews.length - 1],
});
} else {
res.status(404).send({ message: 'Product Not Found' });
}
})
);
export default productRouter;
I also tried to add numRating5 to my productModel.js, and
product.numRating5 = product.reviews.filter((x) => x.rating === 5).length;
after product.rating in productRouter.post(...) in productRouter.js, but that just gave me an Uncaught TypeError: Cannot read properties of undefined (reading 'numRating5') error in the frontend.
I would really appreciate any help or advice on how to fix this. Thank you!
The problem is probably related to the fact that the product has not been loaded from the API when you are trying to access it.
Adding a null-check should prevent the error:
const getNumRating = (num) => {
if (!product) return 0;
return product.reviews.filter((x) => x.rating === num).length;
}

Mongoose one-to-many not working (Nodejs)

I have created 2 Users(Admin and Users) and also i have created many ToDos for a User but here my Todo array is empty in my User Schema. Unable to understand why todo task are not assigned to the User Schema.
UserSchema
var userSchema = new Schema({
name: {
type: String,
required: true,
maxlength: 30,
trim: true
},
role: {
type: Number,
default: 0
},
todos: [{
type: Schema.Types.ObjectId,
ref:"Todo"
}]
});
module.exports = mongoose.model("User", userSchema)
Todo Schema
let Todo = new Schema({
todo_heading: {
type: String
},
todo_desc: {
type: String
},
todo_priority: {
type: String
},
todo_completed: {
type: Boolean
},
user: {
type: Schema.Types.ObjectId,
ref:"User"
}
})
module.exports = mongoose.model('Todo', Todo);
here are my routes
User Route
router.get("/user/:userId/todos", isSignedIn, isAuthenticated, getToDos)
Todo Route
router.get("/", getTodos)
router.get("/:id", getUsertodos);
router.post("/user/:userId/add", addUsertodos);
User Controllers
exports.getToDos = (req, res) => {
User.find({ _id: req.params._id })
.populate("todos")
.exec((err, toDo) => {
if (err) {
res.json(err)
}
res.json(toDo)
})
}
ToDo Controllers
exports.addUsertodos = (req, res) => {
let todo = new Todo(req.body)
todo.save((err, todo) => {
if (err) {
return res.status(400).json({
error: "not saved"
})
}
else {
return res.json(todo)
}
})
}
it should work as expected if you add the objectId of newly created todo to the todos property when you create a user.
//routers/todo.js
var express = require('express');
var router = express.Router();
const Todo = require('../models/Todo');
const User = require('../models/User');
/* GET home page. */
router.get('/', async function (req, res) {
let todos = await Todo.find();
res.json({
todos
});
});
router.post('/todos', async function (req, res) {
//add todos
let {
todo_desc,
todo_heading,
todo_priority,
todo_completed
} = req.body;
try {
//NOTE: for simplicity assigning first user but you can grab it from the params
let user = await User.findOne();
let todo = await Todo.create({
todo_desc,
todo_completed,
todo_priority,
todo_heading,
user: user._id
})
res.json({
message: 'todo created successfully',
todo
});
} catch (err) {
return res.status(500).json({
message: 'Unable to create a todo',
err: JSON.stringify(err)
})
}
});
module.exports = router;
Here is the user route where post route get the string id of created ID and converts it to ObjectId(), assign it to the todos.
var express = require('express');
var router = express.Router();
let _ = require('lodash');
var mongoose = require('mongoose');
const User = require('../models/User');
/* GET users listing. */
router.post("/", async function (req, res) {
let {
name,
todos
} = req.body;
try {
let user = new User();
user.name = name;
let objectIds = todos.split(',').map(id => mongoose.Types.ObjectId(id));
user.todos.push(...objectIds)
await user.save()
console.log("user: ", JSON.stringify(user));
if (_.isEmpty(user)) {
res.status(500).json({
message: 'unable to create user'
})
}
res.json(user);
} catch (err) {
res.status(500).json({
message: 'unable to create user',
err: JSON.stringify(err)
})
}
});
router.get("/", async function (req, res) {
try {
let user = await User.find().populate('todos');
console.log("user: ", JSON.stringify(user));
if (_.isEmpty(user)) {
res.status(500).json({
message: 'unable to find user'
})
}
res.json(user);
} catch (err) {
res.status(500).json({
message: 'unable to find user',
err: JSON.stringify(err)
})
}
});
module.exports = router;
Check out the attached screenshot, the user record now contains the todos assigned to it.
If you want checkout the working code, please visit this repo that i created!!.
Hope this help.Cheers!!

Unable to pull record from array

I am trying to remove an item from an array of objects by using Mongoose 'pull'. I am getting a status code of 200 and apparently everything is fine but the record is not actually removed? The userId in mongo db looks like:
userId: ObjectId("6b275260a6g58308e510721b")
exports.putDislike = (req, res, next) => {
const productId = req.body.productId;
const userId = req.body.userId;
Product.findById(productId)
.then(product => {
if (!product) {
return next(new Error('Product not found.'));
}
product.requests.pull(userId)
return product.save()
.then(result => {
res.status(200).json({ message: "Item request removed." });
})
})
.catch(err => {
res.status(500).json({ message: "Removing request failed." });
});
};
I'm not sure you are using pull correctly, check out this link https://docs.mongodb.com/manual/reference/operator/update/pull/
According to that, i think your code should be somehing like the example below:
exports.putDislike = (req, res, next) => {
const productId = req.body.productId;
const userId = req.body.userId;
Product.update(
{ "_id": productId },
{ $pull: { requests: {userId: userId} } })
.then(result => {
res.status(200).json({ message: "Item request removed." });
})
.catch(err => {
res.status(500).json({ message: "Removing request failed." });
});
};

ExpressJS - populate before save asyc await

I want to populate user in Feed model, and i cant do that, this is what i tried
router.post('/', async (req, res) => {
const newFeed = new Feed(req.body);
try {
const article = await newFeed.populate('created_by');
const finalArticle = await newFeed.save();
res.status(200).json({
success: true,
message: "Successfully created.",
data: finalArticle
})
} catch (err) {
next(err)
}
});

(mongoose) put method does not work

I am creating web API using mongoose.
POST and GET work, but I have no idea how to implement PUT method in mongoose.
Here is what I created:
board.js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const config = require('../config/database');
const BoardSchema = mongoose.Schema({
_id: {
type: String
},
position: {
type: [String]
}
});
const Board = module.exports = mongoose.model('boards', BoardSchema);
module.exports.getBoardById = function (id, callback)
{
Board.findById(id, callback);
}
module.exports.addBoard = function (newBoard, callback)
{
newBoard.save(callback);
}
module.exports.updateBoard = function (newBoard, callback)
{
newBoard.save(callback);
}
users.js
router.put('/board/:id', (req, res, next) =>
{
let newBoard = new Board({
_id: req.params.id,
position: req.body.position
});
Board.updateBoard(newBoard, (err, board) =>
{
if (err)
{
res.json({ newBoard: newBoard, success: false, msg: "Failed to update board" });
}
else
{
res.json({ newBoard: newBoard, success: true, msg: "Board added" });
}
});
});;
Here, in the board.js, I created methods for adding a new board and updating to existing board. .addBoard is working correctly and am able to test it using Postman. But, .updateBoard adds the data when the data does not exist, but does not update any data and returns false as response (just like POST does). Is there any way I can make the PUT method works?
Thank you!
Please let me know if this works for you! I want to introduce you to http://mongoosejs.com/docs/api.html#findbyidandupdate_findByIdAndUpdate
router.put('/board/:id', (req, res) => {
const {id: _id} = req.params // Assigning id to _id which is a es6 feature. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
const {position} = req.body
const newBoard = {
_id,
position
}
Board.findByIdAndUpdate(
_id,
newBoard,
(err, updatedBoard) => {
if (err) {
res.json({
newBoard,
success: false,
msg: 'Failed to update board'
})
} else {
res.json({newBoard, success: true, msg: 'Board added'})
}
}
)
})
why are you using save method while updating?
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const config = require('../config/database');
const BoardSchema = mongoose.Schema({
_id: {
type: String
},
position: {
type: [String]
}
});
const Board = module.exports = mongoose.model('boards', BoardSchema);
module.exports.getBoardById = function (id, callback)
{
Board.findById(id, callback);
}
module.exports.addBoard = function (newBoard, callback)
{
newBoard.save(callback);
}
module.exports.updateBoard = function (condition, update, callback)
{
Board.update(condition,update,callback);
}
in controller
router.put('/board/:id', (req, res, next) =>
{
let newBoard = new Board({
_id: req.params.id,
position: req.body.position
});
Board.updateBoard({ _id: req.params.id } ,newBoard, (err, board) =>
{
if (err)
{
res.json({ newBoard: newBoard, success: false, msg: "Failed to update board" });
}
else
{
res.json({ newBoard: newBoard, success: true, msg: "Board added" });
}
});
});
try this.
As you are using req.body i think you are trying to call a put request from a form (sometimes happens with AJAX requests also). For doing that use method-overide. And set the xhr header as given in the documentation. This will surely work.

Resources