Error in updating profile with image using mongoose and cloudinary - javascript

updateProfile: async function(req, res) {
try {
const update = req.body;
const id = req.params.id;
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
const image = req.files.profileImage;
const cloudFile = await upload(image.tempFilePath);
const profileImage = cloudFile.url
console.log('Loging cloudfile', profileImage)
await User.updateOne(id, { update }, { profileImage }, { new: true },
function(err, doc) {
if (err) {
console.log(err)
}
if (doc) {
return res.status(200).send({ sucess: true, msg: 'Profile updated successful' })
}
});
} catch (error) {
res.status(500).json({ msg: error.message });
}
}
But I'm getting an error of "Callback must be a function, got [object Object]"
I have tried to $set: update and $set: profileImage but still not working.
So the image successful upload into the cloudinary but the update for mongoose is not working.

Upon brief research into the issue, I think you are feeding the arguments in wrong. Objects can be confusing but not to worry.
Your code is:
await User.updateOne(id, { update }, { profileImage }, { new: true }
However, I believe it should be something more like:
await User.updateOne({id: id}, { profileImagine: profileImage, new: true },
The API reference annotates use of the function as:
const filter = { name: 'John Doe' };
const update = { age: 30 };
const oldDocument = await User.updateOne(filter, update);
oldDocument.n; // Number of documents matched
oldDocument.nModified; // Number of documents modified

Related

Node Js: Remove string array element from mongoDB

I have a user schema as follows:
const UserSchema = new mongoose.Schema({
skills: [String]
});
module.exports = mongoose.model("User", UserSchema);
And a Fetch request to delete a skill as follows:
const deleteItem = async (id) => {
try {
await fetch(`http://localhost:5000/api/user/deleteskill`, {
method: "DELETE",
headers: { "Content-Type": "application/JSON", token: accessToken },
body: JSON.stringify({ userid: userid , skill:id}),
})
.then((res) => res.json())
.then((data) => {
console.log("USER SKILLS:", data.userskills);
});
} catch (err) {
console.log(err);
}
};
Server
const deleteSkill = async (req, res) => {
try {
const user = await User.findById(req.body.userid)
//user.skills.pull(req.body.skill);
// removeskill = user.skills.filter(function(item) {
// return item !== req.body.skill
// })
if (user.skills.includes(req.body.skill)) {
res.status(400).json("Item Still Exists");
} else {
res.status(200).json("Item Deleted");
}
} catch (error) {
res.status(500).send({ error: error.message });
}
};
the array is in the following structure
[
'skill1', 'java', 'skill5'
]
I have tried to remove the user skill from the array in several ways but I still get res.status(400).json("Item Still Exists");. What I'm doing wrong?
Use the findOneAndUpdate method to find a document with the user id and update it in one atomic operation:
const deleteSkill = async (req, res) => {
try {
let message = "Item Deleted";
let status = 200;
const user = await User.findOneAndUpdate(
{ _id: req.body.userid },
{ $pull: { skills: req.body.skill } },
{ new: true }
)
if (user && user.skills.includes(req.body.skill)) {
message = "Item Still Exists";
status = 400;
} else if (!user) {
message = "User Not Found";
status = 404;
}
res.status(status).send({ message });
} catch (error) {
res.status(500).send({ error: error.message });
}
};
I believe you want to remove skills from the database then the following function could help you out.
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
var myquery = { userid: userid, skillid: skillid};
dbo.collection("skills").deleteOne(myquery, function(err, obj) {
if (err) throw err;
console.log("1 document deleted");
db.close();
});
});
You have a method of removing elements from arrays, if you want to remove the first one you could use array.shift (more on it here), but if you want to delete it completely from your database you could always, find it and then update it.
User.update({ _id: userid }, { $pull: { "skills": "[skill]" }})

User object is returning undefined when trying to assign one of its attributes to a new variable

I'm trying out this code to create a simple order and then when trying to assign the user.shoppingCart Array to a new variable ("products") it says the user is undefined but for example the address is working just fine and then trying to console.log the user.address and user.shoppingCart it actually prints the correct values. Any ideas?
exports.createOrder = async (req, res) => {
try {
const user = await User.findById(req.user.id);
if (user.shoppingCart.length < 1) {
return res.status(400).json({
status: 'fail',
message: 'Please first add a product to your shopping cart.',
});
}
const address = req.body.address || user.address;
const products = user.shoppingCart;
const total = await getTotal();
const { paymentMethod } = req.body;
const order = await Order.create({
address,
user: user._id,
products,
total,
paymentMethod,
});
res.status(201).json({
status: 'success',
data: {
order,
},
});
} catch (err) {
res.status(500).json({
status: 'fail',
message: err.message,
});
}
};

.save() not correctly saving to mongoDB with async/await

I'm having an issue with refactoring a function used to create a "post", which then saves it on a "user". It works just fine with the .then() syntax, but I can't seem to figure out how to make this work with async/await.
The post is created, and when I look at the User it is supposed to be saved to, the post id shows up on the User. However, the Post never gets a reference to the User id when created. This is what I have currently.
const create = async (req, res) => {
const userId = req.params.id;
try {
const foundUser = await db.User.findById(userId);
const createdPost = await db.Post.create(req.body);
foundUser.posts.push(createdPost._id);
await foundUser.save((err) => {
if (err) return console.log(err);
});
res.json({ post: createdPost });
} catch (error) {
if (error) console.log(error);
res.json({ Error: "No user found."})
}
}
EDIT: As requested, here is a snippet of my schema for posts.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const postSchema = new Schema(
{
title: {
type: String,
required: true,
maxlength: 100,
},
description: {
type: String,
maxlength: 300,
},
date: {
type: Date,
default: Date.now(),
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment",
},
],
},
{ timestamps: true }
);
const Post = mongoose.model("Post", postSchema);
module.exports = Post;
The issue is probably here, you're saving the document, but the await here does nothing since you're passing a callback function, so your code does not wait for the response.
await foundUser.save((err) => {
if (err) return console.log(err);
});
There's no need to catch any errors here either since you're in a try catch, so the correct line of code here would be
await foundUser.save()
So, I decided to take a look back at my way of doing this function while using .then(), and I noticed there was a line that I at first thought was unnecessary. I added req.body.user = userId after finding the User. This then gave me the reference to the User on my Post. So, I tried this with my async-await version and it worked! I'm not sure if this is the "right" way to go about this though.
Below I've included the working code:
const create = async (req, res) => {
const userId = req.params.id;
try {
const foundUser = await db.User.findById(userId);
req.body.user = userId;
const createdPost = await db.Post.create(req.body);
foundUser.posts.push(createdPost._id);
await foundUser.save();
res.json({ post: createdPost });
} catch (error) {
if (error) console.log(error);
res.json({ Error: "No user found."})
}
}

Inability to pull from a nested array

I have this query
router.delete('/:_id', async (req, res) => {
const {_id} = req.params;
const errors = [];
console.log(_id);
await Promise.all([
// Pon.findOneAndDelete({_id}).catch((e) => {
// console.log(e);
// errors.push('Something went wrong. Pon was not deleted');
// }),
// ^^^^^^^^^ this part worked. Wanted to just test the other query
User.findOneAndUpdate({_id: req.user._id}, {$pull: {pons: {_id}}}).catch((e) => {
console.log(1, e);
errors.push('Something went wrong. Pon reference was not deleted from user');
}),
]);
if (errors.length > 0) {
console.log(2, errors);
res.json({ok: false, errors});
} else {
res.json({ok: true});
}
});
I am just trying to remove an element from user object. Here's the object
{
"_id": {
"$oid": "5ea2d8cffe35b93e84f7962b"
},
"pons": [
{
"$oid": "5ea98b181a2be04ec87aa710" // this is what I want to remove
}
],
"email": "test#test.tes",
"password": "$2a$12$VJ0MkcGUs42pikT42qLpyOb0Sd53j9LXH8dY9RdR/GcmUVzJoP8gi",
"__v": 0
}
This query doesn't throw any errors, catch doesn't catch anything, so I don't know what I'm doing wrong. I tried just doing {pons: _id} instead of {pons: {_id}} but no luck.
The _id is correct. Checked with console.log.
What am I missing?
_id is just a String. If you want to match an ObjectId, you have to wrap it like this mongoose.Types.ObjectId(_id)
const ObjectId = mongoose.Types.ObjectId
User.findOneAndUpdate(
{ _id: ObjectId(req.user._id) },
{ $pull: { pons: ObjectId(_id) } }
)
Since you are querying by _id, you could also use User.findByIdAndUpdate() which will wrap req.user._id with ObjectId for you.
const ObjectId = mongoose.Types.ObjectId
User.findByIdAndUpdate(req.user._id, { $pull: { pons: ObjectId(_id) } })

Post data to mongodb

Hi i have end point to post data to mongodb , when i submit a form only ID is submitted I think because am using insert instead of save ,
Here is how it looks:
app.post('/comments', (req, res) => {
const { errors, isVal } = validate(req.body);
if (isVal){
const { author, description } = req.body;
db.collection('comments').insert({ author, description }, (error, result) => {
if (error) {
res.status(500).json({ errors: { global: "Oops something is right!" }});
} else {
res.json({ comments: result.ops[0] });
}
})
} else {
res.status(400).json({ errors });
}
});
The method above is the one saves only ID, other data saved null: I tried to change like this, replacing insert with save some one suggested something like this.
app.post('/comments', (req, res) => {
const { errors, isVal } = validate(req.body);
if (isVal){
const { author, description } = req.body;
db.collection('comments').save({ author, description }, (error, result) => {
if (error) {
res.status(500).json({ errors: { global: "Oops something is right!" }});
} else {
res.json({ comments: result.ops[0] });
}
})
} else {
res.status(400).json({ errors });
}
});
Still the same : here is the result saved in database:
{
"_id": {
"$oid": "5b281457f5b629565c09ce26"
},
"author": null,
"description": null
}
how can I change my method so that it can use save instead of insert?
and what is the different between save and insert in mongodb?
Try with this
let newcollection = db.collection('comments');
newcollection.insert({})

Categories

Resources