Me and my partner need to get the average rating per movie. Movie and Rating are two separate collections on our MongoDB database.
So, first we need to get all the movies. After that, all we should still need is to iterate in a for-loop through the length of the list of movies returned. In every iteration we Rating.find
on the tt_number
of the movie that is currently on the index of the for-loop. At that point, it should calculate an average of all of that movie's ratings and store the result in a string JSON. This is done for every movie.
However, the code I included down here does nothing like that. Instead, the for-loop first completes, and then it performs the Rating.find three times afterwards, except with the tt_number
of the last iterated movie every time.
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);
});
});
Output:
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.' } ] }
Update
This question is not a duplicate of the others presented, as this one deals with response builders and dynamic response content. The others are general on how to handle for-loops and tasks to be completed before others. They come close to what I was looking for, but I hadn't found those either while looking for 2 hours straight, plus they just about miss on what I was looking for.