Why is my Node.js api recognising a duplicate user from MongoDb but still adding an additional user?
I have included unique: true
property for email while declaring the schema for user.
I am also using the mongoose.model.findOne(query, options)
method of mongoose to check if user already exists and it throws the expected "User already exists" response in case of a duplicate email.
However, the user gets added to the DB anyway.
Below is the code for my API:
const express = require('express');
const mongoose = require('mongoose');
const router = express.Router();
const mongoUri = require('../../config/db.json').mongoUri;
const UserModel = require('../../models/user.js');
const options = {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false,
autoIndex: false, // Don't build indexes
poolSize: 5, // Maintain up to 10 socket connections
serverSelectionTimeoutMS: 5000, // Keep trying to send operations for 5 seconds
socketTimeoutMS: 5000, // Close sockets after 45 seconds of inactivity
family: 4 // Use IPv4, skip trying IPv6
};
//@route POST api/user
//@desc Create User
//@access private
router.post('/', async (req, res) => {
const {
email,
name,
password,
permission
} = req.body;
try {
mongoose.connect(mongoUri, options);
var query = UserModel.where({
email: email
});
query.findOne((err, existingUser) => {
if (err) {
return res.status(422).send(err);
}
if (existingUser) {
return res.status(422).send({
error: 'User already exists.'
});
}
});
const user = new UserModel({
name,
email,
password,
permission
})
const newUser = await user.save();
return res.status(200).send(newUser);
} catch (error) {
return res.status(503).send(error);
}
})
module.exports = router;
I am not able to figure out the solution using the documentation and I am unable to find a relevant answer.
I think this is as you create the newUser outside of an asynchronous block of code, so both of them will be executed, the check and creating a new user
so creating a new user does not wait until the email check is done
I suggest you to move creating the new user operation to be inside the call back of the email check
something like that
var query = UserModel.where({
email: email
});
query.findOne((err, existingUser) => {
if (err) {
return res.status(422).send(err);
}
if (existingUser) {
return res.status(422).send({
error: 'User already exists.'
});
} else {
// in the else condition, the email does not exist before in db, then create the user
const user = new UserModel({
name,
email,
password,
permission
})
const newUser = await user.save();
return res.status(200).send(newUser);
}
});
hope it helps