我有《Getting MEAN》一书中的 Express 应用程序示例。我正在使用 Mongoose 连接到 Mongodb。这是文件
{
"_id": {
"$oid": "65537eb149dd64103a4b7950"
},
"name": "Starcups",
"address": "125 High Street, Reading, RG6 1PS",
"rating": 3,
"facilities": [
"Hot drinks",
"Food",
"Premium wifi"
],
"coords": [
-0.9690884,
51.455041
],
"openingTimes": [
{
"days": "Monday - Friday",
"opening": "7:00am",
"closing": "7:00pm",
"closed": false
},
{
"days": "Saturday",
"opening": "8:00am",
"closing": "5:00pm",
"closed": false
},
{
"days": "Sunday",
"closed": true
}
],
"reviews": [
{
"author": "Lekan Yusuf",
"id": {
"$oid": "6560c0dfadc556388f6b8e93"
},
"rating": 4,
"timestamp": {
"$date": "1992-06-11T23:00:00Z"
},
"reviewText": "Good wifi, moderate coffee"
},
{
"author": "Lekan Yusuf",
"id": {
"$oid": "6563c6c0d8b148207dcc9817"
},
"rating": 4,
"timestamp": {
"$date": "1992-06-11T23:00:00Z"
},
"reviewText": "Good wifi, moderate coffee"
}
]
}
我有这条路线:
var express = require('express');
var router = express.Router();
var ctrlReviews =require('../controllers/reviews');
//reviews routes
router.get('/locations/:locationid/reviews/:reviewid', ctrlReviews.reviewsReadOne);
router.post('locations/:locationid/reviews', ctrlReviews.createReview);
router.put('locations/:locationid/reviews/reviewid', ctrlReviews.reviewsUpdateOne);
router.delete('locations/:locationid/reviews/reviewid', ctrlReviews.reviewsDeleteOne);
这是控制器代码:
module.exports.reviewsReadOne = function(req, res){
console.log('in ReviewsReadOne');
if(req.params && req.params.locationid && req.params.reviewid){
console.log('locationid: '+ req.query.locationid + ' reviewid: '+ req.query.reviewid);
Loc.findById(req.query.locationid, 'name reviews').exec(
function(err,location){
var response, review;
if(!location){
sendJsonResponse(res, 404, {"message": "locationid not found"});
return;
} else if (err){
sendJsonResponse(res, 404, err);
return;
}
console.log('location just before "if(location.reviews && location.reviews.length >0)"\n' + location);
console.log('\n reviews: '+ location.reviews);
if(location.reviews && location.reviews.length >0){
review = location.reviews.id(req.params.reviewid);
if(!review){
sendJsonResponse(res, 400, {"message":"Review id not found"});
} else {
console.log('review ' + review)
response ={
location:{
name: location.name,
id: req.query.id
},
review:review
};
sendJsonResponse(res, 200, response);
}
} else {
sendJsonResponse(res, 400, {message:"Not found, locationid and reviewid are both required"});
}
}
);
} else{
sendJsonResponse(res, 400, {"message": "No location id and or review id"});
return;
}
}
当我使用现有的 locationid 和 reviewid 测试 Postman 的 API 时,它给出:
{
"message": "Not found, locationid and reviewid are both required"
}
VSCode 终端给出以下输出:
in ReviewsReadOne
locationid: 65538583fc3b3ac2c0b83a8d reviewid: 6563c74141216ec9d9ec7c38
location just before "if(location.reviews && location.reviews.length >0)"
{
_id: new ObjectId("65538583fc3b3ac2c0b83a8d"),
name: 'Starfi',
reviews: [
{
author: 'Subomi ogunderu',
id: new ObjectId("6563c74141216ec9d9ec7c38"),
rating: 3,
timestamp: 1995-08-11T23:00:00.000Z,
reviewText: 'Excellent wifi and the food is great'
}
]
}
reviews: undefined
GET /api/locations/locationid/reviews/reviewid?locationid=65538583fc3b3ac2c0b83a8d&reviewid=6563c74141216ec9d9ec7c38 400 566.482 ms - 66
显然,定位文档是检索到了,但是测试,
if(location.reviews && location.reviews.length >0)
失败了,这似乎就是我得到的原因
reviews: undefined
在终端中。
请问为什么评论未定义,我该如何解决这个问题。
在此行:
review = location.reviews.id(req.params.reviewid)
您似乎试图使用
id()
,就好像它是 location.reviews
数组的方法一样。不幸的是,猫鼬如果不是这样设计的,因为 location.reviews
是 MongooseArray
类型,它的方法数量有限。
值得庆幸的是,mongodb 有一系列很好的运算符可供选择,您可以使用它们来查找和选择文档的特定属性,这将使您的代码更易于阅读。例如,
$elemMatch
运算符可以让您匹配数组中的元素,如果与$
位置运算符结合使用,意味着您可以选择仅投影该元素。
您可以使用此代码,该代码采用现代
async/await
模式,利用 try/catch
块进行更清晰的错误处理:
module.exports.reviewsReadOne = async function(req, res){ //< Mark function as async
console.log('in ReviewsReadOne');
if(req.params && req.params.locationid && req.params.reviewid){
console.log('locationid: '+ req.query.locationid + ' reviewid: '+ req.query.reviewid);
try{
const location = await Loc.findOne({ //< await the async query
_id: req.query.locationid,
reviews: {
$elemMatch : {
_id: req.query.reviewid
}
}
}, {
name: 1, //< Output location name
'reviews.$': 1 //< Output the matching review
});
if(!location){ //< location will be null if no matches
sendJsonResponse(res, 404, {"message": "Document not found"});
return;
}
sendJsonResponse(res, 200, location);
} catch (err) {
console.log(err);
sendJsonResponse(res, 500, {"message": "Error on server. Check log."});
return;
}
} else{
sendJsonResponse(res, 400, {"message": "No location id and or review id"});
return;
}
}