Sorry if the header was dumb, I am new to code. I am currently trying to build a database for movies and it currently allows me to make duplicate posts of the same on a user "favorite movie list"
I cannot not seem to figure this out or know what or how to ask....
I think the error is in here somewhere:
app.post('/users/:Username/movies/:MovieID', passport.authenticate('jwt', { session:false }), (req, res) => {
Users.findOneAndUpdate({ Username: req.params.Username },
{ $push: { FavoriteMovies: req.params.MovieID }
},
{ new: true }, // this line makes sure that the updated document is returned
(err, updatedUser) => {
if (err) {
console.error(err);
res.status(500).send('Error: ' + err);
} else {
res.json(updatedUser);
}
});
});
Thank you for your time and consideration!
Related
When I click to delete a post, my console is saying TypeError: post.user.posts.deleteOne is not a function. It giving me this error after deleting.
const post = await Post.findByIdAndDelete(id).populate('user'); This code I am deleting the post from Post Schema
await post.user.posts.deleteOne(post)This code is to delete the post from the User Schema. I populated user and assigned it to post and then delete the user's post from this code, but I'm getting the error here.
Below is the controller code
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
const post = await Post.findByIdAndDelete(id).populate('user');
await post.user.posts.deleteOne(post)
if (!post) {
return res.status(500).json({ message: "Unable To Delete" })
}
res.status(200).json({ message: "Deleted Successfully" })
} catch (error) {
console.log(error);
}
}
Client side delete request
const handleDeleteTrue = async () => {
try {
const { data } = await api.delete(`/post/${id}`)
console.log(data)
window.location.reload();
} catch (error) {
console.log(error.response.data.message);
}
};
User model schema
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
username: {
type: String,
required: true,
unique: true
},
email: {
type: String,
required: true,
unqie: true
},
password: {
type: String,
required: true,
minlength: 6
},
posts: [{ type: mongoose.Types.ObjectId, ref: "Post", required: true }]
});
export default mongoose.model('User', userSchema);
Im able to delete the post from the post model schema, but in this pic, which shows the user model schema, that same post that was deleted is not deleted here. This is the problem Im trying to solve.
What I can seem to understand in your function below is that you're trying to delete a single post and also checking if post exists first
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
const post = await Post.findByIdAndDelete(id).populate('user');
await post.user.posts.deleteOne(post)
if (!post) {
return res.status(500).json({ message: "Unable To Delete" })
}
res.status(200).json({ message: "Deleted Successfully" })
catch (error) {
console.log(error);
}
}
I'd suggest you try this
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
//check if document exists in mongoDB collection
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(500).json({ message: "Unable To Delete" }) }
await Post.deleteOne(id)
res.status(200).json({ message: "Deleted Successfully" })
catch (error) {
console.log(error);
}
}
I found out the answer. My user model schema for post was an array so I had to use $pull to delete it.
This is the code that worked for me
await post.user.posts.pull(post)
await post.user.save()
You can't use findOneAndDelete on populate to delete one object from an array. it doesn't work that way. Use This Instead.
const result = await User.findOneAndUpdate(
{ _id: Id },
{ $pull: { post:PostId } },
{ new: true }
);
You can find More on Pull and Push Operations on BlogLink
I am trying to push a new object to an array with objects inside another object (see DB Schema here: MongoDB set-up). Trying to push to notes within subtopics[2] object within the topic.
This is the code but it ends up deleting the specified subtopic id:
router.patch('/:topicId/:subtopicId/note', async (req, res) => {
try {
const subtopicNote = await Note.update(
{_id: req.params.topicId},
{subtopics :
{ _id: req.params.subtopicId,
$push: {
notes:
{note: req.body.note}
}
}
}
);
res.json(subtopicNote);
} catch (err) {
res.json({ messsage: err})
}
})
This worked for me :)
router.patch('/:topicId/:subtopicId/note', async (req, res) => {
try {
const subtopicNote = await Note.updateOne(
{_id: req.params.topicId, subtopics : {"$elemMatch": {"_id":req.params.subtopicId}}},
{ $push : {
'subtopics.$.notes': {note: req.body.note}
}
}
)
res.json(subtopicNote);
} catch (err) {
res.json({ message: err})
}
})
When I try to update a record, it deletes the objects instead of updating them. I know my routes are correct since it's working in Postman.
Routes:
router.route('/update/:id').post(function (req, res) {
Bet.findById({ _id: req.params.id }, function (err, bets) {
if (!bets)
res.status(404).send("Data not found.");
else {
bets.result = req.body.result;
bets.profit = req.body.profit;
bets.save().then(bets => {
res.json('Update complete.');
})
.catch(err => {
res.status(400).send("Unable to update.");
});
}
});
});
App.js
handleSelection = async (value, id, event, key) => {
const obj = {
result: "Win",
profit: profits,
}
axios.post("http://localhost:5000/bet/update/" + key.id, obj)
.then(res => console.log(res.data));
}
Example of a json;
{
"_id": "5ddfe84f07a48861b4c0c153",
"name": "asd",
"profit": "-10",
"result": "Loss"
}
When my code runs, it becomes like this:
{
"_id": "5ddfe84f07a48861b4c0c153",
"name": "asd"
}
Actually it is not deleting your document, but overwriting existing fields with empty values. And the reason is most probably that you don't send result and profit values in POST request body.
So I advise you to console.log req.body inside your route to see if result and values are there:
By the way you can shorten your code using findByIdAndUpdate method like this:
router.route('/update/:id').post(async (req, res) => {
console.log("req.body: ", req.body);
try {
const { result, profit } = req.body;
const response = await Bet.findByIdAndUpdate(req.params.id, {result,profit}, { new: true });
if (!response) return res.status(400).send("Data not found");
res.json("Update complete");
} catch (err) {
res.status(500).send("Something went wrong");
}
})
To send a POST request, you can use postman, with this body:
And in your node console.log will log this:
After you see it works with postman, you can add the content-type headers to axios.post and try if it works. Also be sure the console.log("obj: ", obj) logs your object with the data you want.
console.log("obj: ", obj);
axios.post("http://localhost:5000/bet/update/" + key.id, obj,
{
headers: { "content-type": "application/json" }
})
I want to push a string in an array in a MongoDB document using React/NodeJS/MongoDB,
Here's my code in React
async function toggleLike() {
try {
const dataUser = await axios.post(
`http://localhost:5000/user/${props.auth.user.id}/add/moviesLiked/${props.match.params.id}`);
console.log("user ", dataUser);
forceUpdate();
} catch (error) {
console.log(error);
}
Here's my code in NodeJS
router.post("/user/:user/add/moviesLiked/:movie", function(req, res) {
console.log("in api function add");
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
return;
}
const db = client.db("ofilms-demo");
const collection = db.collection("users");
collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } }
);
console.log("req params user ", req.params.user);
console.log("req params movie ", req.params.movie);
client.close();
}
);
});
Here's the model of an user in Mongoose
const UserSchema = new Schema({
moviesLiked: Array,
moviesDisliked: Array,
});
All my console.log show the right thing, but I still don't have the data pushed in the array,
Can somebody help me ? Thank you,
collection.update is asynchronous, so you need to wait for it to finish executing before closing your connection to Mongo and returning a response to the client.
You can wait for the update operation to complete by either passing a call back to the update method or using the async/await javascript feature.
Passing a call back function:
router.post("/user/:user/add/moviesLiked/:movie", function (req, res) {
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
return;
}
const db = client.db("ofilms-demo");
const collection = db.collection("users");
collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } },
function (error, result) { // The callback function
if (error) {
// Handle the error and send a respone to the user
} else {
// Make use of the result and send a response to the user
}
client.close();
}
);
}
);
});
Using async/await:
// Add the async keyword before declaring the function
router.post("/user/:user/add/moviesLiked/:movie", async function (req, res) {
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
return;
}
const db = client.db("ofilms-demo");
const collection = db.collection("users");
try {
// Add the await keyword before the update call
await collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } },
);
// Send response to your client
} catch (err) {
// Handle any possible error
}
client.close();
console.log("req params user ", req.params.user);
console.log("req params movie ", req.params.movie);
}
);
});
After DB i/o operation is done you should send back the response to your client something like this:
use try-catch to get the error message without crashing the whole node server.
Don't forget to send back the response to client otherwise, the client-side will keep waiting for server response until it's timeout reached
Node.js
router.post("/user/:user/add/moviesLiked/:movie", async (req, res) =>{
console.log("in api function add");
mongo.connect(
url,
{
useNewUrlParser: true,
useUnifiedTopology: true
},
(err, client) => {
if (err) {
console.error(err);
res.status(500).send({"message":"error occured", err})
return;
}
try{
const db = client.db("ofilms-demo");
const collection = db.collection("users");
const response = await collection.update(
{ _id: req.params.user },
{ $addToSet: { moviesLiked: req.params.movie } }
);
console.log("req params user ", req.params.user);
console.log("req params movie ", req.params.movie);
//send back the response
res.status(200).send({response, "message":"your profile is successfully updated."})
client.close();
}catch(err){
//check what is the error in your Nodejs console (Not browser console)
console.log(err)
//send back response
res.status(500).send({"message":"error occured", err})
}
);
}
});
MongoDB is itself schema-less. you don't have to provide schema. if you want to provide your own schema I'd recommend using mongoose. & mongoose arrays
I am trying to add DELETE to my api, but am getting a 404: Not Found for everything I try. All of the GET and POST methods work. This is using the "Points" model that contains points, each with a unique id. I am trying to add a call to delete a point by its id.
Action
export function deletePointById(identifier) {
return dispatch => {
return axios.delete('/api/points/' + identifier)
}
}
Route for DELETE (doesn't work)
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' });
};
});
Here is an existing GET that works fine
Action
export function getPointsBySession(session){
return dispatch => {
return axios.get('/api/points/session/' + session)
}
}
Route for GET
router.get('/session/:session', (req, res) => {
Points.query({
select: ['id', 'number', 'quadrant', 'level', 'title', 'category'],
where: {sessionId: req.params.session}
}).fetchAll().then(point => {
res.json({ point });
})
});
It looks like your issue might be that theres an extra brace and semicolon ( };) in your code:
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' });
}; // <-- HERE
});
You also need to remove the semicolon on the line above the one I added the comment to.
It will look like this:
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' })
});