Mongodb 两个集合用外键连接

问题描述 投票:0回答:1

我在前端使用 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://stackoverflow.com/questions/5681851/mongodb-combine-data-from-multiple-collections-into-one-how

https://hevodata.com/learn/mongodb-join-two-collections/

https://www.mongodb.com/docs/v4.2/core/views/join-collections-with-view/

我想通过外键加入两个集合,当用户登录时,他们的测验结果将在“quizresult”集合中提交

javascript node.js mongodb
1个回答
0
投票

您是否在集合或实例上调用了 .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() 方法使这变得容易。

© www.soinside.com 2019 - 2024. All rights reserved.