Mongoose save method seems to not be working - mongodb

I am trying to create a REST API. I am pretty new to the back end and am just practicing on my own for the time being. For my code, I know it's bad practice to store the plain text password but again, this is completely for practice and will never go live. I will also add encryption at a later point for practice.
My issue is I am not sure why my API does not work. I see where it fails, it fails in the catch block when I try to save a user but I do not get any error to tell me what is wrong exactly, besides the once I force. I have another part on this website that follows almost the exact same logic and it works perfectly but for this one it does not. I have no idea how to solve my issue but after googling I still cannot figure it out. It looks perfectly fine too me, but as mentioned I am pretty new to the backend.
This is my controller function:
const signup = async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return next(new HttpError('Invalid inputs passed, please check your data', 422));
}
const { name, email, password, places } = req.body;
let existingUser;
try {
existingUser = await User.findOne({email: email}) // finds one document matching our criteria we set
} catch(err) {
const error = new HttpError('Signing up failed, please try again later', 500);
return next(error);
}
if (existingUser) {
const error = new HttpError('User exists already, please login instead', 422);
return next(error);
}
const createdUser = new User({
name,
email,
image: 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260',
password,
places
});
try {
await createdUser.save();
} catch(err) {
const error = new HttpError(
'Signing up failed', 500
);
return next(error);
}
res.status(201).json({user: createdUser.toObject({ getters:true })});
};
I use Postman to send the request to my API endpoint with all of the correct information. Based on what I recieve back it is failing in the try catch block of await createdUser.save()

For anyone who finds this from google this was my solution:
First I suggest you add this into your save method to try and diagnose the problem
await createdUser.save(function(err){
if(err){
console.log(err);
return;
}
});
This help me greatly as it gave me more information on how to solve it.It turns out my problem was because I misspelled a field in my Schema. So extremely simple solution!

Related

Endpoint Not Responding

I'm trying to make CRUD app using mongodb atlas and express when i need to make an GET endpoint its not responding and keeps loading here the code
Get Endpoint:
app.get('/getTodo',(req, res) => {
const cursor = db.getDB().collection(coll).find({});
cursor.toArray(( todos) => {
res.send(todos);
});
}
});
I tried to catch the error using try catch there was no error then i tried to log something after it it logged. I also tried to user async and await samething nothing changed.
what should I do?? what I'm doing wrong??

Axios Delete Not Working In React App But Working In PostMan/Insomnia

Axios DELETE works when I send a request through postman but on my react app it doesn't. I'm passing the _id that MongoDB assigns the entry. I'm initiating ObjectId and it still doesn't work. I also double checked if I was using the correct route, which I was.
In my app I have click function that calls SaveBook. That part I feel okay about. Let me know if I need to share something else.
SaveBook in AuthActions.js on the front end
export const saveBook = ({books, user, book, _id}) => {
return function () {
console.log(`This is id ${JSON.stringify(_id)}`)
const savedIndex = books.indexOf(book);
if (savedIndex >= 0) {
console.log(savedIndex)
axios
.delete("/api/users/wishlist", {_id})
} else {
console.log(savedIndex)
// console.log(`Adding ${book.book.title} to faves...`);
axios
.post("/api/users/dashboard", {book, user})
.then(console.log("success"))
.catch (err =>
json(err)
);
}
}
};
In users.js the delete operation on the server side
router.delete('/wishlist', (req, res) => {
const db = mongoUtil.getDb();
db.db("mern-auth-2").collection("savedbooks")
.deleteOne({_id:ObjectId(req.body._id)})
.then(res.json(res.data))
});
I realized req.body wasn't the correct choice for the Delete method and used url params/ req.params to send the _id. This works well.
Fixed this line in authActions.js
axios
.delete("/api/users/wishlist/" + _id,)
Fixed these few lines in Users.js
router.delete('/wishlist/:id', (req, res) => {
const db = mongoUtil.getDb();
db.db("mern-auth-2").collection("savedbooks")
// .deleteOne({_id:ObjectId(req.body._id)})
.deleteOne({_id:ObjectId(req.params.id)})

How mongoose middleware works and what is next()?

userSchema.pre('save',async function(next){
//hash the password before saving user to database
next()
})
Hey guys I'm trying to understand the concept of middleware in mongoose. Assuming that I have an userSchema that I run the pre hook on to hash the password before saving the user to the database. On the surface, as far as I understand, the above code that I have will hash the password (not the important part for this question) and then call next() to signal that the function is done. However, I am trying to understand how things work under the hood. I want to know what is next() ? Can you guys walk me through an example of how everything works together under the hood from start to end once the code get executed or somehow help me to have a better understanding of this concept? Thanks
Short : with the pre method you can register listeners for certain events of your Schemas. So pre('save', callback) will fire whenever you save a document of said Model. pre means it will execute before the event, so it can be used (for example) to hash a password before saving it to the document.
However, you have several options to define them, see below :
The combination of using an async callback function and providing the next parameter is not necessary, you can either :
use normal callback with next parameter
the next parameter is a function provided to you by mongoose to have a way out, or to tell mongoose you are done and to continue with the next step in the execution chain. Also it is possible to pass an Error to next it will stop the execution chain.
schema.pre('save', function(next) {
// do stuff
if (error) { return next(new Error("something went wrong"); }
return next(null);
});
use async callback
Here the execution chain will continue once your async callback has finished. If there is an error and you want to break/stop execution chain you just throw it
schema.pre('save', async function() {
// do stuff
await doStuff()
await doMoreStuff()
if (error) { throw new Error("something went wrong"); }
return;
});
Straight from the docs : https://mongoosejs.com/docs/middleware.html#pre
Example
const { Schema, model } = require('mongoose');
const SomeSchema = new Schema ({
name : { type : String }
});
SomeSchema.pre('save', function (next) {
console.log('pre save fired!');
return next();
});
const Some = model('Some', SomeSchema);
console.log('before create');
const doc = new Some({ name : 'test' });
doc.save((err) => {
console.log('after saved');
});
This will output
before create
pre save fired!
after saved

How can I catch errors in my firebase function when setting a document fails?

I have a firebase cloud function to create a user document with user data whenever a user registers. How would I return an error when the set() fails? Since this is not an http request (an I don't want to use an http request in this case) I have no response. So how would I catch errors?
export const onUserCreated = functions.region('europe-west1').auth.user().onCreate(async user => {
const privateUserData = {
phoneNumber: user.phoneNumber
}
const publicUserData = {
name: 'Nameless'
}
try
{
await firestore.doc('users').collection('private').doc('data').set(privateUserData);
}catch(error)
{
//What do I put here?
}
try
{
await firestore.doc('users').collection('public').doc('data').set(publicUserData);
}catch(error)
{
//What do I put here?
}
});
You can't "return" an error, since the client doesn't even "know" about this function running, there is nobody to respond to.
You can make a registration collection, and in your function make a document there for the current user (using the uid as the document id). In that document, you can put any information you'd like your user to know (status, errors, etc).
So your clients would have to add a listener to this document to learn about their registration.
In your particular code, I think the error is in doc('users'). I guess you meant doc('users/'+user.uid).
Your catch -block will receive errors that occur on your set -call:
try {
await firestore.doc('users').collection('public').doc('data').set(publicUserData);
} catch (error) {
// here you have the error info.
}

MongoDB Converting Circular Structure to JSON error

I'm trying to query a collection of users using Mongoose in a Node API.
The handler looks like this:
exports.getUsers = async function(req, res, next) {
try {
let users = db.User.find();
return res.status(200).json(users);
} catch(e) {
return next(e);
}
};
This returns an error that reads Converting circular structure to JSON. When I console.log() the results of db.User.find(), I get a Query object. I've checked everything else. All of my other routes are working normally.
Well...I figured it out. I'll post the answer that I discovered in case anyone else is trying to figure this out. It turns out, through a little bit more careful reading of the documentation, that the Query object that is returned has to be executed. There are two ways to execute it - with a callback function or by returning a promise (but not both). I found this page on queries in the mongoose docs helpful. My final handler looked like this.
exports.getUsers = async function(req, res, next) {
try {
db.User.find()
.then(users => {
return res.status(200).json(users);
});
} catch(e) {
return next(e);
}
};
Next time I guess I'll dig around for a few more minutes before asking.
Edit to add:
Found a second solution. Due to the use of the async function, I also was able to use following inside the try block.
let users = await db.User.find();
return res.status(200).json(users);