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." });
});
};
Related
I have the following express code. If I try to get a document with a non-existent id, I get nothing. The problem is that I get 200 as response status and I don't get the Failed message. The code jumps every time into "then".
const Mymodel = require('../model/Mymodel');
const Single = (req, res) => {
const id = req.params.id;
Mymodel.findById(id)
.then(result => {
res.send(result);
})
.catch(err => {
console.log(err);
res.status(404).send({"Failed": "Document not found"});
});
}
your finding query response is null so this is not an error. if you send res.status(404).send({"Failed": "Document not found"}); response for not found use this.
const Mymodel = require('../model/Mymodel');
const Single = (req, res) => {
const id = req.params.id;
Mymodel.findById(id)
.then(result => {
if(result){
res.send(result);
}else{
res.status(404).send({"Failed": "Document not found"});
}
})
.catch(err => {
console.log(err);
res.status(404).send({"Failed": "Document not found"});
});
}
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,
});
}
});
};
I have created three collections,
family {familyname , _id}
root {rootname familyId _id}
child{childname rootId familyId _id}
Now if I delete family, root, and child should also be deleted
So far, I have tried this but it's not working
router.delete("/:familyId", (req, res, next) => {
const id = req.params.familyId;
Family.remove({ _id: id })
Root.remove({ _id: id })
Child.remove({ _id: id })
.exec()
.then(result => {
res.status(200).json({
message: 'deleted',
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
You can use the promises returned by the .remove() method as follows:
router.delete("/:familyId", (req, res, next) => {
const id = req.params.familyId;
const family = Family.remove({ _id: id });
const root = Root.remove({ familyId: id });
const child = Child.remove({ familyId: id });
Promise.all([family, root, child]).then(result => {
console.log(result);
res.status(200).json({
message: 'deleted',
});
}).catch(err => {
console.error(err);
res.status(500).json({
error: err
});
});
});
I am trying to add test data for my test:
const chai = require("chai");
const expect = require("chai").expect;
chai.use(require("chai-http"));
const app = require("../server.js"); // Our app
const user = require("../app/controllers/user.controller.js");
describe("API endpoint /users", function() {
this.timeout(5000); // How long to wait for a response (ms)
before(function() {
const users = [
{
email: "ssss#ss.com",
givenName: "eee",
familyName: "www2"
},
{
email: "ssss#ss.com",
givenName: "eee",
familyName: "www2"
}
];
user.create(users);
done();
});
// GET - List all data
it("should return all users", function() {
return chai.request(app).get("/users").then(function(res) {
expect(res).to.have.status(200);
expect(res).to.be.json;
expect(res.body).to.be.an("array");
});
});
});
I get the error:
1) API endpoint /users
"before all" hook:
TypeError: Cannot destructure property email of 'undefined' or 'null'.
at Object.exports.create (app\controllers\user.controller.js:5:13)
How can I add test data?
Controller:
const user = require("../models/user.model.js");
const validator = require("email-validator");
// Create and Save a new user
exports.create = (req, res) => {
const { query: { email, givenName, familyName } } = req;
// Validate request
if (!validator.validate(email) || !givenName || !familyName) {
return res.status(400).send({
message:
"Please use a valid email address, given name and family name."
});
}
// Create a user
const User = new user({
email,
givenName,
familyName
});
// Save user in the database
User.save()
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Error occurred while creating the user."
});
});
};
// Retrieve and return all users from the database.
exports.findAll = (req, res) => {
user
.find()
.then(users => {
res.send(users);
})
.catch(err => {
res.status(500).send({
message:
err.message || "An error occurred while retrieving users."
});
});
};
// Find a single user with a userId
exports.findOne = (req, res) => {
user
.findById(req.params.userId)
.then(user => {
if (!user) {
return res.status(404).send({
message: "user not found with id " + req.params.userId
});
}
res.send(user);
})
.catch(err => {
if (err.kind === "ObjectId") {
return res.status(404).send({
message: "user not found with id " + req.params.userId
});
}
return res.status(500).send({
message: "Error retrieving user with id " + req.params.userId
});
});
};
// Update a user identified by the userId in the request
exports.update = (req, res) => {
// Validate Request
if (!req.body.content) {
return res.status(400).send({
message: "user content can not be empty"
});
}
// Find user and update it with the request body
user
.findByIdAndUpdate(
req.params.userId,
{
title: req.body.title || "Untitled user",
content: req.body.content
},
{ new: true }
)
.then(user => {
if (!user) {
return res.status(404).send({
message: "user not found with id " + req.params.userId
});
}
res.send(user);
})
.catch(err => {
if (err.kind === "ObjectId") {
return res.status(404).send({
message: "user not found with id " + req.params.userId
});
}
return res.status(500).send({
message: "Error updating user with id " + req.params.userId
});
});
};
// Delete a user with the specified userId in the request
exports.delete = (req, res) => {
user
.findByIdAndRemove(req.params.userId)
.then(user => {
if (!user) {
return res.status(404).send({
message: "user not found with id " + req.params.userId
});
}
res.send({ message: "user deleted successfully!" });
})
.catch(err => {
if (err.kind === "ObjectId" || err.name === "NotFound") {
return res.status(404).send({
message: "user not found with id " + req.params.userId
});
}
return res.status(500).send({
message: "Could not delete user with id " + req.params.userId
});
});
};
create function expects a single user while it receives an array of users as an argument. The problem with it is that it's a middleware, it doesn't return a promise, so it cannot be efficiently chained. It also causes side effects and calls res.send while this is not needed for what it's used here.
Mongoose model should be used directly here, its create accepts an array. The block should return a promise in order to not cause race conditions in tests:
const User = require(".../user.model.js");
...
before(function() {
const users = [...];
return User.create(users);
});
I'm trying to increase or decrease the number of ads of a user. I can increment the number but I can't decrement it.
const updateUserAdsNumber = (saveOrDelete) => {
finalSchema.post(saveOrDelete, (ad, next) => {
const increaseOrDecrease = saveOrDelete === 'save' ? 1 : -1;
User.findOneAndUpdate(
{_id: ad.adInfo.userId},
{$inc: {adsPublished: increaseOrDecrease}},
(err, user) => {
if (err) return console.error('User ads could not increase or decrease', err.message);
}
);
next();
});
};
updateUserAdsNumber('save');
updateUserAdsNumber('deleteOne');
finalSchema.plugin(mongooseUniqueValidator);
const AdModel = mongoose.model('Ad', finalSchema);
Here's the route that deletes the ad:
router.delete('/:id', verifyTokenMiddleware, (req, res) => {
const id = req.params.id;
const {tokenDecoded} = req;
Ad.deleteOne({'adInfo.userId': tokenDecoded.userId, _id: mongoose.Types.ObjectId(id)}, (err) => {
if(err){
res.status(400).send({
message: 'The ad could not be deleted. (Error_message = ' + err.message + ')'
});
} else {
res.send({
message: 'Ad deleted successfully!'
})
}
})
});
I'm using mongoose#5.2.13 and Mongo 3.6.5, what might go wrong? I could put the logic directly into router.delete but I prefer to hook it before schema export.
As stated in documentation of mongoose I should update the document, not the collection. So, instead of:
router.delete('/:id', verifyTokenMiddleware, (req, res) => {
const id = req.params.id;
const {tokenDecoded} = req;
Ad.deleteOne({'adInfo.userId': tokenDecoded.userId, _id:
mongoose.Types.ObjectId(id)}, (err) => {
if(err){
res.status(400).send({
message: 'The ad could not be deleted. (Error_message = ' + err.message + ')'
});
} else {
res.send({
message: 'Ad deleted successfully!'
})
}
})
});
I used this:
router.delete('/:id', verifyTokenMiddleware, (req, res) => {
const id = req.params.id;
const {tokenDecoded} = req;
Ad.findById({'adInfo.userId': tokenDecoded.userId, _id:
mongoose.Types.ObjectId(id)}, (err, ad) => {
if (err) {
res.status(500).send({
message: 'The ad could not be deleted. (Error_message = ' +
err.message + ')'
});
} else {
ad.remove(err => { <---- here's the document remove
if (err) {
console.log(err);
}
});
res.send({
message: 'Ad deleted successfully!'
});
}
});
});
and switched from updateUserAdsNumber('deleteOne') to updateUserAdsNumber('remove') in the first method above (in the question) and everything works as expected.