我在前端使用 HTML、CSS 和 JavaScript,在后端使用 Node.js。对于数据库,我使用 MongoDB。在添加身份验证页面之前,当随机用户尝试测验时,他们的分数将保存在 MongoDB 的“quizresults”集合中。但是,添加身份验证页面后,当用户成功注册时,他们的数据开始保存在 MongoDB“用户”集合中。但是登录后,当用户提交测验时,他们的分数会显示在屏幕上,但数据不会保存在 MongoDB 的“quizresults”集合中。为了解决这个问题,我尝试在“用户”和“测验结果”这两个集合之间建立连接,但问题仍然存在。
用户.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
const User = mongoose.model('User', userSchema);
module.exports = User;
quizResult.js
const mongoose = require('mongoose');
const quizResultSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User', // Refers to the 'User' model
required: true
},
correctAnswers: {
type: Number,
required: true
},
totalQuestions: {
type: Number,
required: true
},
totalScore: {
type: Number,
required: true
}
});
const QuizResult = mongoose.model('QuizResult', quizResultSchema);
module.exports = QuizResult;
authRoutes.js
// authRoutes.js
const express = require('express');
const router = express.Router();
const authController = require('../controllers/authController');
// Route for user registration (POST request)
router.post('/register', authController.register);
// Route for user login (POST request)
router.post('/login', authController.login);
module.exports = router;
用户路由.js
const express = require('express');
const router = express.Router();
const { authenticateUser } = require('../middlewares/authMiddleware');
const { generateToken } = require('../utils/jwtUtils');
// Placeholder route handler for user login
router.post('/login', authenticateUser, (req, res) => {
// Handle user login logic here
// Assuming the user is authenticated, generate a JWT token
const token = generateToken(req.user.userId);
// Send the token back to the client
res.json({ token });
});
module.exports = router;
app.js
const express = require('express');
const mongoose = require('mongoose');
const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
const path = require('path');
const crypto = require('crypto');
const User = require('./models/user');
const authRoutes = require('./routes/authRoutes');
const app = express();
// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/stallman', { useNewUrlParser: true, useUnifiedTopology: true });
mongoose.connection.on('error', console.error.bind(console, 'MongoDB connection error:'));
// Generate a secure random string to use as a session secret
const sessionSecret = crypto.randomBytes(64).toString('hex');
// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(session({
secret: sessionSecret,
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// Passport Configuration
passport.use(new LocalStrategy({ usernameField: 'email' }, async (email, password, done) => {
try {
const user = await User.findOne({ email });
if (!user) {
return done(null, false, { message: 'User not found.' });
}
const match = await bcrypt.compare(password, user.password);
if (!match) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
} catch (err) {
return done(err);
}
}));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id);
done(null, user);
} catch (err) {
done(err);
}
});
// Serve static files from the public directory
app.use(express.static(path.join(__dirname, 'public')));
// Routes
app.use('/auth', authRoutes);
// Define route for the login page
app.get('/login', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'login.html'));
});
// Define route for the register page
app.get('/register', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'register.html'));
});
// Define route for user login
app.post('/login', async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (!user) {
console.log('User not found:', email);
return res.status(400).json({ message: 'User not found.' });
}
console.log('Stored Password:', user.password);
console.log('Provided Password:', password);
const match = await bcrypt.compare(password, user.password);
console.log('Password Match:', match);
if (!match) {
return res.status(400).json({ message: 'Incorrect password.' });
}
// Redirect to homepage after successful login
res.redirect('/');
} catch (error) {
console.error('Error during login:', error);
res.status(500).json({ message: 'Internal Server Error' });
}
});
// Define route for the root path
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
我已经尝试过这些链接
https://hevodata.com/learn/mongodb-join-two-collections/
https://www.mongodb.com/docs/v4.2/core/views/join-collections-with-view/
我想通过外键加入两个集合,当用户登录时,他们的测验结果将在“quizresult”集合中提交
您是否在集合或实例上调用了 .save() ?我在您的代码中没有看到保存 QuizResults 的位置。
类似:
const doc = new QuizResult();
doc.user = '6592008029c8c3e4dc76256c';
doc.correctAnswers = 5;
doc.totalQuestions = 5;
doc.totalScore = 100;
doc.save();
我在代码中没有看到将文档保存到 QuizResult 集合的任何地方。
注意:Mongodb 是非关系型的,因此没有外键的概念,但您可以使用 $lookup 嵌入和查找文档引用。在 mongoose 中,他们在文档实例上使用 .populate() 方法使这变得容易。