TypeError:无法读取未定义的属性(读取“集合”),在第 82 行出现错误,其中有 db.collection()

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

我正在开发一个 MongoDB 项目,我需要为数据库配置服务器,任何人都可以帮助解决这些问题。 以下添加文件供参考,请回答这个问题!!

index.mjs

import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import students from "./routes/students.mjs";
import auth from "./routes/auth.mjs";

dotenv.config();

const app = express();
app.use(cors());
app.use(express.json());

// Define routes
app.use("/api/students", students);
app.use("/api/auth", auth);

// Error handling middleware
app.use((err, req, res, next) => {
    console.error(err.stack); // Log the error stack trace for debugging
    res.status(500).send("Uh oh! An unexpected error occurred.");
});

// Start the server
const port = process.env.PORT || 3000;
app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
});

auth.mjs


import express from "express";
import bcrypt from "bcrypt";
import db from "../db/conn.mjs"; // Adjust path as needed
import { ObjectId } from "mongodb";

const saltRounds = 10;
const router = express.Router();

// Helper function to validate password
async function validatePassword(password, hash) {
    try {
        const match = await bcrypt.compare(password, hash);
        return match;
    } catch (err) {
        console.error(err.message);
        return false;
    }
}

// Sign-In Route
router.post('/signin', async (req, res) => {
    try {
        const { email, password } = req.body;

        // Ensure MongoDB connection is established
        await db();

        // Check if email exists in DB
        const user = await db.collection('users').findOne({ email });
        if (!user) {
            return res.status(400).send('User not found');
        }

        // Validate password
        const isValidPassword = await validatePassword(password, user.password);
        if (!isValidPassword) {
            return res.status(400).send('Invalid password');
        }

        res.status(200).send('Sign in successful');
    } catch (err) {
        console.error(err);
        res.status(500).send('An error occurred');
    }
});

// Sign-Out Route
router.post('/signout', (req, res) => {
    res.status(200).send('Sign out successful');
});

// Sign-Up Route
router.post('/signup', async (req, res) => {
    const {
        fullName, email, phone, branch,
        currYear, yearOfJoining, password,
        acmMemberId
    } = req.body;

    // Check if any required fields are missing
    const errors = {};
    if (!fullName) errors.fullName = "Full Name is required";
    if (!email) errors.email = "Email is required";
    if (!phone) errors.phone = "Phone number is required";
    if (!branch) errors.branch = "Branch is required";
    if (!currYear) errors.currYear = "Current year is required";
    if (!yearOfJoining) errors.yearOfJoining = "Year of joining is required";
    if (!password) errors.password = "Password is required";
    if (!acmMemberId) errors.acmMemberId = "ACM Member ID is required";

    // If there are errors, return them
    if (Object.keys(errors).length > 0) {
        return res.status(400).json(errors);
    }

    // If all required fields are present, continue with processing
    try {
        // Hash password
        const hashedPassword = await bcrypt.hash(password, saltRounds);

        // Insert new user into DB
        const result = await db.collection('users').insertOne({
            fullName, email, phone, branch,
            currYear, yearOfJoining, password: hashedPassword,
            acmMemberId, points: 0
        });

        res.status(201).send('User created successfully');
    } catch (err) {
        console.error(err);
        res.status(500).send('An error occurred');
    }
});


export default router;

conn.mjs

import { MongoClient } from "mongodb";
import dotenv from "dotenv";

dotenv.config();

const connectionString = `mongodb+srv://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASS}@acm-backend.jbgki1q.mongodb.net`;
const client = new MongoClient(connectionString);

let db;

(async () => {
    try {
        await client.connect();
        db = client.db("acm-backend");
        console.log("Connected to MongoDB");
    } catch (e) {
        console.error("Failed to connect to MongoDB", e);
    }
})();

export default db;

我尝试使用 postman 进行 POST api 调用,但无法获取输出或返回所需的 json 答案。我期待将数据插入数据库。

{
  "fullName": "John Doe",
  "email": "[email protected]",
  "phone": "1234567890",
  "branch": "CSE",
  "currYear": "3",
  "yearOfJoining": "2020",
  "password": "securepassword",
  "acmMemberId": "12345",
  "points": "0"
}

javascript mongodb express nosql postman
1个回答
0
投票

出现此问题的原因是,当您的路由尝试访问 MongoDB 连接(和数据库对象)时,可能无法建立它。在 conn.mjs 中,db 变量是异步分配的,在正确初始化之前可能会有延迟。

在这种情况下,一个好的做法是确保在启动服务器之前正确建立数据库连接。以下是修改设置的方法:

首先,修改您的 conn.mjs 以导出一个函数,以确保建立数据库连接并返回 db 对象。

import { MongoClient } from "mongodb";
import dotenv from "dotenv";

dotenv.config();

const connectionString = `mongodb+srv://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASS}@acm-backend.jbgki1q.mongodb.net`;
const client = new MongoClient(connectionString);

let db;

const connectToDatabase = async () => {
    if (db) {
        return db;
    }

    try {
        await client.connect();
        db = client.db("acm-backend");
        console.log("Connected to MongoDB");
        return db;
    } catch (e) {
        console.error("Failed to connect to MongoDB", e);
        throw e;
    }
};

export default connectToDatabase;

接下来,修改index.mjs以确保服务器仅在建立数据库连接后启动。

import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import students from "./routes/students.mjs";
import auth from "./routes/auth.mjs";
import connectToDatabase from "./db/conn.mjs";

dotenv.config();

const app = express();
app.use(cors());
app.use(express.json());

// Define routes
app.use("/api/students", students);
app.use("/api/auth", auth);

// Error handling middleware
app.use((err, req, res, next) => {
    console.error(err.stack); // Log the error stack trace for debugging
    res.status(500).send("Uh oh! An unexpected error occurred.");
});

const startServer = async () => {
    try {
        await connectToDatabase(); // Ensure database connection is established
        const port = process.env.PORT || 3000;
        app.listen(port, () => {
            console.log(`Server is running on port ${port}`);
        });
    } catch (err) {
        console.error("Failed to start server", err);
    }
};

startServer();

最后,修改您的 auth.mjs 以使用在尝试使用它之前确保数据库连接的功能。

import express from "express";
import bcrypt from "bcrypt";
import connectToDatabase from "../db/conn.mjs"; // Adjust path as needed
import { ObjectId } from "mongodb";

const saltRounds = 10;
const router = express.Router();

// Helper function to validate password
async function validatePassword(password, hash) {
    try {
        const match = await bcrypt.compare(password, hash);
        return match;
    } catch (err) {
        console.error(err.message);
        return false;
    }
}

// Sign-In Route
router.post('/signin', async (req, res) => {
    try {
        const { email, password } = req.body;

        const db = await connectToDatabase(); // Ensure MongoDB connection is established

        // Check if email exists in DB
        const user = await db.collection('users').findOne({ email });
        if (!user) {
            return res.status(400).send('User not found');
        }

        // Validate password
        const isValidPassword = await validatePassword(password, user.password);
        if (!isValidPassword) {
            return res.status(400).send('Invalid password');
        }

        res.status(200).send('Sign in successful');
    } catch (err) {
        console.error(err);
        res.status(500).send('An error occurred');
    }
});

// Sign-Out Route
router.post('/signout', (req, res) => {
    res.status(200).send('Sign out successful');
});

// Sign-Up Route
router.post('/signup', async (req, res) => {
    const {
        fullName, email, phone, branch,
        currYear, yearOfJoining, password,
        acmMemberId
    } = req.body;

    // Check if any required fields are missing
    const errors = {};
    if (!fullName) errors.fullName = "Full Name is required";
    if (!email) errors.email = "Email is required";
    if (!phone) errors.phone = "Phone number is required";
    if (!branch) errors.branch = "Branch is required";
    if (!currYear) errors.currYear = "Current year is required";
    if (!yearOfJoining) errors.yearOfJoining = "Year of joining is required";
    if (!password) errors.password = "Password is required";
    if (!acmMemberId) errors.acmMemberId = "ACM Member ID is required";

    // If there are errors, return them
    if (Object.keys(errors).length > 0) {
        return res.status(400).json(errors);
    }

    // If all required fields are present, continue with processing
    try {
        const db = await connectToDatabase(); // Ensure MongoDB connection is established

        // Hash password
        const hashedPassword = await bcrypt.hash(password, saltRounds);

        // Insert new user into DB
        const result = await db.collection('users').insertOne({
            fullName, email, phone, branch,
            currYear, yearOfJoining, password: hashedPassword,
            acmMemberId, points: 0
        });

        res.status(201).send('User created successfully');
    } catch (err) {
        console.error(err);
        res.status(500).send('An error occurred');
    }
});

export default router;

通过进行这些更改,您可以确保在路由中使用数据库连接之前正确建立数据库连接,从而防止出现 TypeError:无法读取未定义的属性(读取“集合”)错误。

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