我和我的搭档需要获得每部电影的平均评分。电影和评级是 MongoDB 数据库中两个独立的集合。
所以,首先我们需要获取所有电影。之后,我们仍然需要在 for 循环中迭代返回的电影列表的长度。在每次迭代中,我们对当前位于 for 循环索引上的电影的 Rating.find
进行 tt_number
。此时,它应该计算该电影所有评分的平均值并将结果存储在字符串 JSON 中。每部电影都会这样做。
但是,我在此处包含的代码没有执行类似的操作。相反,for 循环首先完成,然后执行三次 Rating.find,每次都使用最后一次迭代电影的 tt_number
。
var express = require('express');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Notflix', {useMongoClient: true});
var Movie = require('../model/movies.js');
var Rating = require('../model/ratings.js');
var jwt = require('jsonwebtoken');
var router = express.Router();
router.get('/', function (req, res) {
var jsonString = '{"The average ratings":[]}';
var obj = JSON.parse(jsonString);
var moviett_number;
Movie.find({}, function (err, movies) {
if (err) {
res.status(500);
res.json({errorMessage: '500 SERVER-SIDE ERROR - No list of movies to get the average ratings of could be found.'});
}
for (var i = 0; i < movies.length; i++) {
//TODO: I THINK THIS FOR LOOP IS COMPLETED FULLY BEFORE FINALLY THE RATING.FIND IS DONE???????
//Go through the list of all movies, getting the ratings for each...
moviett_number = movies[i].tt_number;
console.log(i + " - " + moviett_number);
Rating.find({'tt_number': moviett_number}, function (err, movieRatings) {
//Get all the ratings for the current movie...
if (err) {
res.status(500);
res.json({errorMessage: '500 SERVER-SIDE ERROR - No list of average ratings for this movie could be found.'});
return;
}
if (movieRatings > 0) {
//If it has ratings, calculate the average rating.
var amountOfRatings;
var average = 0;
for (amountOfRatings = 0; amountOfRatings < movieRatings.length; amountOfRatings++) {
average += parseInt(movieRatings[amountOfRatings].rating);
}
average = Math.round((average / amountOfRatings) * 100) / 100;
//Add the average rating for this movie to the response jsonString.
obj["The average ratings"].push({
averageRatingMessage: 'Movie with tt_number = [' + moviett_number + '] has the following average rating.',
averageRating: average
});
} else {
//Add a notice that this movie does not have any ratings and therefore no average rating either to the response jsonString.
obj["The average ratings"].push({noRatingMessage: 'Movie with tt_number = [' + moviett_number + "] has no ratings yet."});
}
//TODO: WATCH FOR THIS CONSOLE.LOG, IT SHOWS A WEIRD ISSUE.
console.log(obj);
});
}
jsonString = JSON.stringify(obj);
//TODO: ASYNCHRONOUS ISSUE, RESPONSE IS SET BEFORE THE CODE ABOVE IS DONE, BECAUSE THE PROGRAM CONTINUES EVEN IF THE FOR LOOP ISN'T DONE YET!
console.log(jsonString);
res.status(200);
res.json(jsonString);
});
});
输出:
0 - 123
1 - 456
2 - 789
{"The average ratings":[]}
{ 'The average ratings': [ { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' } ] }
{ 'The average ratings':
[ { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' },
{ noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' } ] }
{ 'The average ratings':
[ { noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' },
{ noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' },
{ noRatingMessage: 'Movie with tt_number = [789] has no ratings yet.' } ] }
更新
此问题与其他问题不同,因为此问题涉及响应生成器和动态响应内容。其他的一般是关于如何处理 for 循环和在其他之前完成的任务。它们很接近我要找的东西,但我在连续寻找 2 个小时的时候也没有找到它们,而且它们几乎没有找到我要找的东西。
最佳答案
Model.find()
方法是异步的,因此您在从数据库返回结果之前发送结果。获取所有数据后,您将需要使用回调来实际发送响应。
// callback when all your Rating.find() are complete
function done(movies) {
res.json(movies);
}
// get the movies
Movie.find({}, function (err, movies) {
// loop over the results
movies.forEach(function(movie, i) {
// get the Rating for this Movie
Rating.find({'tt_number': movie.tt_number}, function (err, ratings) {
// add the rating
movie.rating = ratings.reduce(function(total, rating) {
total += rating;
return total;
}, 0) / ratings.length;
// this is the last one, call done()
if (movies.length-1 === i) {
done(movies);
}
});
}
});
关于Javascript 和 Mongoose for 循环在执行内部 .find 之前完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46737664/