How to save cloudinary url to mongoDb - node.js

I'm trying to save Cloudinary url to MongoDB but really don't know what is wrong with my code, because it's not working.
here is my code :
exports.test = asyncHandler(async (req, res, next) => {
const email = req.params.email;
console.log
cloudinary.uploader
.upload(req.file.path, { folder: 'avatar' })
.then((result) => {
console.log(result);// shows correctly on console
const { secure_url, public_id } = result;
console.log('url:',secure_url)// url & secure_url shows correctly on console
console.log('public_url:',public_id);
Resume.findOneAndUpdate(
{
email:email,
},
{ $set: { imagePath: secure_url} },
{
new: true,
fields: {
imagePath: 1,
},
}
);
console.log('upload successful!!');
})
.catch((error) => {
console.log(error);
});
});
I use $set because I want the field created if it didn't exist before. Also, I get the public_id and secure_url successfully from Cloudinary, but it didn't save in my database.
here is the output from console.log(result):
{
asset_id: '1ee919b68e258c9778097e40671ac710',
public_id: 'seawedkarowxgnipz8hq',
url: 'http://res.cloudinary.com/workaman/image/upload/v1656322947/seawedkarowxgnipz8hq.png',
secure_url: 'https://res.cloudinary.com/workaman/image/upload/v1656322947/seawedkarowxgnipz8hq.png',
original_filename: 'file_cuyajt',
}
and here is how i defined the model:
const ResumeSchema = new mongoose.Schema({
imagePath:{
type:String,
required:false
},
cloudinary_Id:{
type:String,
required:false
},
})
It seems I'm missing out on something but I really can't figure it out. when I submit from the frontend, I get the message "console.log('upload successfully!!')" but nothing is saved.

I think the issue here is that you're mixing up the MongoDB Node.js SDK with Mongoose a little bit. In the code that you shared you have both ResumeSchema and Resume - just check that those are correct.
In Mongoose the findOneAndUpdate() method does not have a $set option. The MongoDB CLI and subsequently their Node.js Driver also has findOneAndUpdate(), but the signature of that function and it's usage options somewhat differ.
Without seeing the rest of your code it's hard to tell what is exactly going on but my gut feeling is that you've mixed up these two methods. I hope this helps.

Related

Why is findByIdAndUpdate() not updating an _id's information? (using $set)

I'm a beginner in MongoDB and have been following a tutorial from one year ago. I send a PUT request with the following json:
{
"username": "NoMore"
}
Then I use findByIdAndUpdate() with the _id being pulled from the url's :id params. The function is async, but await is used on the update function. Despite the code seeming to have worked one year ago, I can not find any updated information regarding this online.
My entire function is as follows:
router.put('/:id', verifyTokenAndAuthorization, async (req, res) => {
if (req.body.password) {
req.body.password = CryptoJS.AES.encrypt(
req.body.password,
process.env.PASS_SEC
).toString();
}
try {
const updatedUser = await User.findByIdAndUpdate(
req.params.id,
{
$set: req.body,
},
{ new: true },
);
res.status(200).json(updatedUser);
} catch(err) {
res.status(500).json(err);
}
})
I have tried setting the _id manually as a string, but the code still went to an error 500. I also preset the req.body which did not change the result.
I am expecting for the user's username to become the username sent in the PUT request.
I didn't import the model (User) so there was no connection to MongoDB.
I put the following code at the top:
const User = require('../models/User');
Now it works fine.

Deleting object from mongoose database not working if site is not refreshed

app.delete("/api/persons/:id", (req, res, next) => {
Person.findByIdAndDelete(req.params.id)
.then((result) => {
res.status(204).end();
})
.catch((error) => next(error));
});
Not sure how to even explain this properly, but there is my delete method. It works fine for objects that are allready in the databases, but if I add a new one and I dont refresh the site, I get error: Cast to ObjectId failed for value "undefined" (type string) at path "_id" for model "Person"
Below is my mongoose schema if that helps:
const personSchema = new mongoose.Schema({
name: { type: String, required: true },
number: { type: Number, required: true },
});
personSchema.set("toJSON", {
transform: (document, returnedObject) => {
returnedObject.id = returnedObject._id.toString();
delete returnedObject._id;
delete returnedObject.__v;
},
});
My guess is you're optimistically updating your frontend with the new Person without waiting for a successful DB response with the new data. That is a valid technique, but gets you into trouble if you're not careful.
My suggestion would be to also send the new value from the database back to your app right away say it can stay in sync. You likely have no _id value on the front end if you're optimistically updating the app before a DB response.
Something like this:
app.post("api/person/new", async (req, res) => {
try {
const person = new Person(req.body)
await person.save()
res.status(201).send({ person })
} catch (err) {
res.status(500).send({ err })
}
})
And then more importantly, your API handler on the frontend needs to take that returned person value and use it to update the values on your front end, so it has access to the _id property for immediate deletion. And if there's an error creating the person for any reason, you can remove the person from the front end, or handle it however you wish.
I don't know what your app is built with, so I can write a sample bit of code for it.

Mongoose not saving record after array is updated

I've seen a couple similar posts, but I can't get anything to work. The following is for a podcast episode topic suggestion app. It's meant to upvote a topic by adding a user ID to an array of user IDs saved to the topic object. Everything seems like it works, but topic.save() isn't actually saving.
router.post('/upvote/:id', auth, async (req, res) => {
try{
var topic = await Topic.findById(req.params.id);
const reqId = req.body._id;
if(topic.upvotes.includes(reqId)){
res.status(409).send('Topic already upvoted.');
}
console.log(`pre-update: ${topic}`);
topic.set({
upvotes: topic.upvotes.push(reqId)
});
console.log(`post-update: ${topic}`);
try{
//topic.markModified('topic.upvotes');
topic = await topic.save();
res.status(201).send(topic);
} catch{
next();
};
} catch{
res.status(404).send('Topic with given ID not found.');
};
});
I tried a few different variations on topic.markModified() because I saw that suggested on other posts, but nothing worked.
Here's what those two console.log()s show:
pre-update: {
upvotes: [],
_id: 612d701dd6bbfd3c5c36c906,
name: 'a topic',
description: 'is described',
category: 61217a75f30c6c826af9076b,
__v: 0
}
post-update: {
upvotes: [ 612996b46f21d2086c9d4d52 ],
_id: 612d701dd6bbfd3c5c36c906,
name: 'a topic',
description: 'is described',
category: 61217a75f30c6c826af9076b,
__v: 0
}
These look like it should work perfectly.
The 404 response at the very end is what's actually getting sent when I try this. I'm using express-async-errors & if the next() in the nested catch block was getting called, it would send 500.
Any suggestions?
I am actually not sure what exactly your trying to do. If you want to add a new value to a field only at a particular place then put or patch is to be used not post. post will update the whole document. and patch put is for partial updation.
Can you refer the sample code which I have given, hope that would be helpful for you in one or the other way.
router.put("/:id", [auth, validateObjectId], async (req, res) => {
const { error } = validateMovie(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
let genre = await Genre.findById(req.body.genreId);
console.log(genre);
if (!genre) {
return res.status(400).send("No genre found with given id");
}
let movieDetails = await Movie.findByIdAndUpdate(
req.params.id,
{
title: req.body.title,
numberInStock: req.body.numberInStock,
dailyRentalRate: req.body.dailyRentalRate,
liked: req.body.liked,
genre: {
_id: genre.id,
name: genre.name,
},
}, //when using patch method, then you need not have to write this whole thing. instead just write req.body
{ new: true }
);
if (!movieDetails) {
return res.status(404).send("No such movie details found.");
}
res.send(movieDetails);
});
I figured it out. I think mongoose doesn't like it if you try to push() a new element like a normal array.
I used addToSet() instead and it worked.
https://mongoosejs.com/docs/api/array.html#mongoosearray_MongooseArray-addToSet

Mongoose .save() returns empty error object, does not save in DB

I am trying to learn MongoDB and typescript but currently running into some issues when trying to create my first document.
When I make a post request from postman, I get "Sending request" for 5 seconds, then it times out and returns an empty error object:
{
"message": {}
}
and the posted data is not saved in my mongoDB.
I first set up connection like this in my server:
mongoose.connect(<string> process.env.DB_CONNECTION, { useNewUrlParser: true}, () =>
console.log("connected to DB!")
);
and get back the correct statement logged, so I am connected.
I have a model that looks like this:
import { model, Schema, Model, Document } from "mongoose";
export interface IUser extends Document {
name: string,
}
const UserSchema: Schema = new Schema(
{
name: {
type: Schema.Types.String,
required: true,
},
},
<any> {timeStamps: true}
);
const User: Model<IUser> = model<IUser>('User', UserSchema);
export default User;
The problem could be in there, but I don’t think it is.
Then, here is my post request for the endpoint I call:
router.post('/add', async (req: Request, res: Response): Promise<any> => {
try {
const user: IUser = new User({
name: req.body.name
});
const savedUser: IUser = await user.save();
res.status(200).json(savedUser);
} catch (err: any) {
res.status(500).json({message: err});
console.log("There was an error");
}
})
Here is where I believe the error is becuase every time the request gets stuck on awaiting the .save()
Any help would be great! Thanks!
The issue was with the initial database connection, the password contained characters that that weren't being encoded. One solution to encode special characters is to make use of the built-in encodeURIComponent() function.

Creating unique index via mongodb native driver

There is a code:
const { MongoClient } = require('mongodb')
const db = MongoClient.connect('mongodb://172.17.0.2:27017/test')
db
.then(
async dataBase => {
eduDb = dataBase.db('edu-service-accounts')
const accounts = eduDb.collection('accounts')
await accounts.createIndex({ email: 1 }, { unique: true })
accounts.insertOne({ email: '123' })
}
)
Code above creates an index, but that is no unique. I already read official docs for native mongoDB driver, but can't handle it.
And yes, I've deleted all old indexex before testing that code.
Can someone please show a code that really create an index with unique.
I mean not part of official doc, or something like that - I need code that works.
NOTE: I tested that code with local db and mlab - the same result.
Like the documentation says: db.createIndex(collectionname, index[, options], callback) the creation returns an index. Try to log the result of the callback. Maybe you are getting an error from the db.
Try something like:
// your connection stuff
accounts.createIndex({ email: 1 }, { unique: true }, function(err, result) {
if(err) {
console.log(err);
} else {
console.log(result);
}
});
After that please provide us the logs.

Resources