使用curl提交评论时触发TypeError:无法读取undefined的insertOne属性
问题:调用curl添加评论时触发TypeError: Cannot read properties of undefined (reading 'insertOne')
使用以下curl命令提交评论时出现错误:
curl -X POST http://localhost:4444/api/v1/reviews/new -H "Content-Type:application/json" -d '{"movieId":12,"user":"sara","review":"good"}'
报错信息:
TypeError: Cannot read properties of undefined (reading 'insertOne')
相关代码文件
reviews.controller.js
import reviewsDAO from "../dao/reviewsDAO.js"; export default class ReviewsController{ static async apiPostReview(req, res, next) { try { const movieId = parseInt(req.body.movieId) const review = req.body.review const user = req.body.user console.log('movieId', movieId) const reviewResponse = await reviewsDAO.addReview( movieId, user, review ) res.json({ status: "success" }) } catch (e) { res.status(500).json({ error: e.message }) } } static async apiGetReview(req, res, next) { try { let id = req.params.id || {} let review = await reviewsDAO.getReview(id) if (!review) { res.status(404).json({ error: "Not found" }) return } res.json(review) } catch (e) { console.log(`api, ${e}`) res.status(500).json({ error: e }) } } static async apiUpdateReview(req, res, next) { try { const reviewId = req.params.id const review = req.body.review const user = req.body.user const reviewResponse = await reviewsDAO.updateReview( reviewId, user, review ) var { error } = reviewResponse if (error) { res.status(400).json({ error }) } if (reviewResponse.modifiedCount === 0) { throw new Error( "unable to update review", ) } res.json({ status: "success" }) } catch (e) { res.status(500).json({ error: e.message }) } } static async apiDeleteReview(req, res, next) { try { const reviewId = req.params.id const reviewResponse = await reviewsDAO.deleteReview(reviewId) res.json({ status: "success" }) } catch (e) { res.status(500).json({ error: e.message }) } } static async apiGetReviews(req, res, next) { try { let id = req.params.id || {} let reviews = await reviewsDAO.getReviewsByMovieId(id) if (!reviews) { res.status(404).json({ error: "Not found" }) return } res.json(reviews) } catch (e) { console.log(`api, ${e}`) res.status(500).json({ error: e }) } } }
reviewsDAO.js
import mongodb from 'mongodb'; const ObjectID=mongodb.ObjectID; let reviews; export default class ReviewsDAO{ static async injectDB(conn){ if(reviews){ return } try{ reviews = await conn.db("reviews").collection("reviews"); } catch(e){ console.error(`Unable to establish collection handles in userDAO: ${e}..`); }; }; static async addReview(movieId,user,review){ try{ const reviewDoc={ movieId:movieId, user:user, review:review } return await reviews.insertOne(reviewDoc); }catch(e){ console.error(`Unable to post review: ${e}`); return{error:e}; }; }; static async getReview(reviewId){ try{ return await reviews.findOne({_id:ObjectID(reviewId)}) }catch(e){ console.error(`Unable to get review: ${e}`); return{error:e}; }; }; static async updateReview(reviewId,user,review){ try{ const updateResponse=await review.updateOne({_id:ObjectID(reviewId)}, {$set:{user:user,review:review}}); return updateResponse; }catch(e){ console.error(`Unable to update review: ${e}`); return{error:e}; }; }; static async getReviewByMovieId(movieId){ try{ const cursor=await reviews.find({movieId: parseInt(movieId)}); return cursor.toArray(); }catch(e){ console.error(`Unable to get review: ${e}`); return{error:e}; }; }; };
reviews.route.js
import express from 'express'; import ReviewsCtrl from "./reviews.controller.js"; const router=express.Router(); router.route("/movie/:id").get(ReviewsCtrl.apiGetReviews); router.route("/new").post(ReviewsCtrl.apiPostReview); router.route("/:id") .get(ReviewsCtrl.apiGetReviews) .put(ReviewsCtrl.apiUpdateReview) .delete(ReviewsCtrl.apiDeleteReview) export default router;
moviedb.js
import app from './server.js'; import ReviewsDAO from "./dao/reviewsDAO.js"; import mongodb from 'mongodb'; import dotenv from 'dotenv'; const MongoClient=mongodb.MongoClient dotenv.config(); const mongo_username = process.env.MONGO_USERNAME; const mongo_password = process.env.MONGO_PASSWORD; const port=4444; MongoClient.connect(`mongodb+srv://${mongo_username}:${mongo_password}@cluster0.b5f7prn.mongodb.net/test`, { maxPoolSize: 50, wtimeoutMS: 2500, useNewUrlParser: true }) .catch(err => { console.error(err.stack) console.error("Error connecting to the database:", err.message) process.exit(1) }) .then(async client => { await ReviewsDAO.injectDB(client) app.listen(port, () => { console.log(`listening on port ${port}`) }) })
问题分析与修复方案
核心错误原因
TypeError: Cannot read properties of undefined (reading 'insertOne') 说明调用reviews.insertOne()时,reviews变量是undefined,即MongoDB集合未被正确初始化。
具体修复点
匹配数据库连接目标
在moviedb.js的连接字符串中指定的数据库是test,但reviewsDAO.js的injectDB方法尝试连接reviews数据库。需确保目标数据库存在,或修改injectDB方法匹配连接字符串中的数据库:static async injectDB(conn){ if(reviews){ return } try{ // 改为连接test库,或确保reviews库已创建 reviews = await conn.db("test").collection("reviews"); } catch(e){ // 修正日志中的DAO名称(原userDAO应为reviewsDAO) console.error(`Unable to establish collection handles in reviewsDAO: ${e}..`); }; };修复updateReview方法的变量名错误
updateReview中误写为review.updateOne,应该是reviews.updateOne(缺少复数s):static async updateReview(reviewId,user,review){ try{ const updateResponse=await reviews.updateOne({_id:ObjectID(reviewId)}, {$set:{user:user,review:review}}); return updateResponse; }catch(e){ console.error(`Unable to update review: ${e}`); return{error:e}; }; };统一方法名匹配
reviews.controller.js中调用reviewsDAO.getReviewsByMovieId,但reviewsDAO.js中的方法名是getReviewByMovieId(缺少复数s),需统一方法名:// reviewsDAO.js中修改方法名 static async getReviewsByMovieId(movieId){ try{ const cursor=await reviews.find({movieId: parseInt(movieId)}); return cursor.toArray(); }catch(e){ console.error(`Unable to get reviews: ${e}`); return{error:e}; }; };补充缺失的deleteReview方法
reviews.controller.js中调用了reviewsDAO.deleteReview,但DAO文件中未实现该方法,需补充:// reviewsDAO.js中添加 static async deleteReview(reviewId){ try{ const deleteResponse=await reviews.deleteOne({_id:ObjectID(reviewId)}); return deleteResponse; }catch(e){ console.error(`Unable to delete review: ${e}`); return{error:e}; }; };
完成以上修复后,重启服务再执行curl命令,即可正常提交评论。
内容的提问来源于stack exchange,提问作者Razan Alsaedi
相关产品推荐
相关产品推荐

