Mongoose中Model.findOne()失效问题求助
Hey there! Let's figure out why your User.findOne() is failing and fix those hidden issues in your code. Here's what's going wrong and how to fix it step by step:
1. Database Connection Conflict
You're using both MongoClient (native MongoDB driver) and Mongoose to connect to your database. Mongoose has its own built-in connection system, so mixing the two causes conflicts—this is almost certainly why your Mongoose queries like findOne() aren't working.
Fix: Remove the MongoClient code and use Mongoose's native connect() method instead:
mongoose.connect('mongodb://localhost:27017/userDb', { useNewUrlParser: true }) .then(() => console.log("Mongo DB Connected...!")) .catch(err => console.error("Connection error:", err));
2. Mixed Async/Await and Callbacks (Unhandled Errors)
In your /register route, you're mixing async/await with bcrypt's callback syntax, which creates race conditions and silent failures. You also aren't awaiting user.save() or handling its errors, which can crash your app without feedback.
Fix: Use bcrypt's promise-based methods (with await) instead of callbacks, and properly handle all async operations:
// Inside /register route const salt = await bcrypt.genSalt(10); const passwordHash = await bcrypt.hash(req.body.password, salt); user = new User({ username: req.body.username, password: passwordHash }); await user.save(); // Await the save operation to ensure it completes res.send('Registered');
3. Unnecessary hash Field in User Schema
Bcrypt's generated hash already includes the salt—you don't need to store the salt separately. Your hash field is redundant and can be removed entirely.
Fix: Update your UserSchema:
const UserSchema = new Schema({ username: { type: String, required: true, minlength: 5, maxlength: 50 }, password: { type: String, required: true, minlength: 5, maxlength: 1024 } });
4. Wrong Password Comparison in Login Route
You're using bcrypt.hash() to compare passwords, which generates a new hash instead of checking if the entered password matches the stored hash. You should use bcrypt.compare() for this task.
Fix: Replace the hash comparison with compare:
// Inside /login route const isPasswordValid = await bcrypt.compare(req.body.password, user.password); if (isPasswordValid) { res.send('You are logged in!'); } else { res.status(400).send('Incorrect password'); }
5. Missing Error Handling for Async Routes
Your async routes don't have proper try/catch blocks—any uncaught errors will crash your app without logging. Wrap all async code in error handlers to catch issues and send meaningful responses.
Full Fixed Code
Here's the complete corrected code with all fixes applied:
const express = require('express'); const bcrypt = require('bcryptjs'); const mongoose = require('mongoose'); const app = express(); app.use(express.json()); // Mongoose Database Connection mongoose.connect('mongodb://localhost:27017/userDb', { useNewUrlParser: true }) .then(() => console.log("Mongo DB Connected...!")) .catch(err => console.error("Connection error:", err)); // User Schema & Model const Schema = mongoose.Schema; const UserSchema = new Schema({ username: { type: String, required: true, minlength: 5, maxlength: 50 }, password: { type: String, required: true, minlength: 5, maxlength: 1024 } }); const User = mongoose.model('User', UserSchema); // Register New User app.post('/register', async (req, res) => { try { console.log('try registering : ', req.body); // Check if user already exists let user = await User.findOne({ username: req.body.username }); if (user) { return res.status(400).send('That user already exists!'); } // Encrypt Password const salt = await bcrypt.genSalt(10); const passwordHash = await bcrypt.hash(req.body.password, salt); // Create and save user user = new User({ username: req.body.username, password: passwordHash }); await user.save(); res.send('Registered'); } catch (err) { console.error(err); res.status(500).send('Server error occurred during registration'); } }); // Login User app.post('/login', async (req, res) => { try { console.log('try Login : ', req.body); // Find user by username let user = await User.findOne({ username: req.body.username }); if (!user) { return res.status(400).send('Incorrect username'); } // Validate password const isPasswordValid = await bcrypt.compare(req.body.password, user.password); if (isPasswordValid) { res.send('You are logged in!'); } else { res.status(400).send('Incorrect password'); } } catch (err) { console.error(err); res.status(500).send('Server error occurred during login'); } }); // PORT const port = process.env.PORT || 3020; app.listen(port, () => console.log(`listening on port ${port}...`));
Why This Works
- The database connection is now handled correctly by Mongoose, so queries like
findOne()will function as expected. - Async operations are properly awaited, eliminating race conditions and silent failures.
- Password handling uses bcrypt's intended methods for hashing and comparison.
- All errors are caught and logged, with meaningful responses sent to the client instead of crashing the app silently.
内容的提问来源于stack exchange,提问作者Saloni Sikdar

