0

Hi I am new to node and I am trying to run a mongoose query with multiple queries in one request and I've run into a problem that just doesn't make sense. I am retrieving energy history data stored in mongodb for the previous 7 days. I comment out from day 4 to 7 the request works, but with the code from day 4 - 7 uncommented I am thrown this error:

story.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsDayAgo[0].fromgrid 
                                                                ^TypeError: Cannot read property 'fromgrid' of undefined

This occurs after the fourDaysAgo query.

Here is the code in the request:

httpsRouter.get('/api/weekhistory', function(req, res) {

  var history = {kwhsNow: '', kwhsToday: '', kwhsDayAgo: '', kwhsTwoDaysAgo: '', kwhsThreeDaysAgo: '', kwhsFourDaysAgo: '', kwhsFiveDaysAgo: '', kwhsSixDaysAgo: '', kwhsSevenDaysAgo: ''};

      kwhsNowQuery = eagleData.eagleKwhs.find(),
      kwhsNowQuery.sort('-_id');
      kwhsNowQuery.limit(1);
      kwhsNowQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        history.kwhsNow = data;
    });       

  var sinceToday = moment().hours(0).minutes(0).seconds(0).format('x');

  var sinceTodayQuery = eagleData.eagleKwhs.find();
      sinceTodayQuery.where('_id').gte(sinceToday - 10000).lte(sinceToday + 10000); 
      sinceTodayQuery.limit(1);
      sinceTodayQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)
        console.log('Since today: ',data[0].fromgrid);  
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid;  
        history.kwhsToday = data;

    });

  var dayAgo = moment().subtract(1, 'days').hours(0).minutes(0).seconds(0).format('x');

  var dayAgoQuery = eagleData.eagleKwhs.find();
      dayAgoQuery.where('_id').gte(dayAgo - 10000).lte(dayAgo + 10000); 
      dayAgoQuery.limit(1);
      dayAgoQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)
        console.log('Day Ago: ',data[0].fromgrid);    
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid;  
        history.kwhsDayAgo = data;
        res.json(history); 
        console.log(history);// return all in JSON format       
    });         

  var twoDaysAgo = moment().subtract(2, 'days').hours(0).minutes(0).seconds(0).format('x');

  var twoDaysAgoQuery = eagleData.eagleKwhs.find();
      twoDaysAgoQuery.where('_id').gte(twoDaysAgo - 10000).lte(twoDaysAgo + 10000); 
      twoDaysAgoQuery.limit(1);
      twoDaysAgoQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        console.log('Two Days Ago: ',data[0].fromgrid);    
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid;  
        history.kwhsTwoDaysAgo = data;

    });

  var threeDaysAgo = moment().subtract(3, 'days').hours(0).minutes(0).seconds(0).format('x');

  var threeDaysAgoQuery = eagleData.eagleKwhs.find();
      threeDaysAgoQuery.where('_id').gte(threeDaysAgo - 10000).lte(threeDaysAgo + 10000); 
      threeDaysAgoQuery.limit(1);
      threeDaysAgoQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        console.log('Three Days Ago: ',data[0].fromgrid);    
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid;  
        history.kwhsThreeDaysAgo = data;
    });


  var fourDaysAgo = moment().subtract(4, 'days').hours(0).minutes(0).seconds(0).format('x');    

  var fourDaysAgoQuery = eagleData.eagleKwhs.find();
      fourDaysAgoQuery.where('_id').gte(fourDaysAgo - 10000).lte(fourDaysAgo + 10000); 
      fourDaysAgoQuery.limit(1);
      fourDaysAgoQuery.exec(function(err, data) {
         //if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        console.log('Four Days Ago: ',data[0].fromgrid);                    //history.kwhsToday[0].fromgrid -
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid;  
        history.kwhsFourDaysAgo = data;
    });

  var fiveDaysAgo = moment().subtract(5, 'days').hours(0).minutes(0).seconds(0).format('x');    

  var fiveDaysAgoQuery = eagleData.eagleKwhs.find();
      fiveDaysAgoQuery.where('_id').gte(fiveDaysAgo - 10000).lte(fiveDaysAgo + 10000); 
      fiveDaysAgoQuery.limit(1);
      fiveDaysAgoQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        console.log('Five Days Ago: ',data[0].fromgrid);    
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid - history.fourDaysAgo[0].fromgrid;  
        history.kwhsFiveDaysAgo = data;
    });

 var sixDaysAgo = moment().subtract(6, 'days').hours(0).minutes(0).seconds(0).format('x');    

  var sixDaysAgoQuery = eagleData.eagleKwhs.find();
      sixDaysAgoQuery.where('_id').gte(sixDaysAgo - 10000).lte(sixDaysAgo + 10000); 
      sixDaysAgoQuery.limit(1);
      sixDaysAgoQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        console.log('Six Days Ago: ',data[0].fromgrid);    
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid - history.fourDaysAgo[0].fromgrid - history.fiveDaysAgo[0].fromgrid;  
        history.kwhsSixDaysAgo = data;
    });

 var sevenDaysAgo = moment().subtract(7, 'days').hours(0).minutes(0).seconds(0).format('x');    

  var sevenDaysAgoQuery = eagleData.eagleKwhs.find();
      sevenDaysAgoQuery.where('_id').gte(sevenDaysAgo - 10000).lte(sevenDaysAgo + 10000); 
      sevenDaysAgoQuery.limit(1);
      sevenDaysAgoQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        console.log('Seven Days Ago: ',data[0].fromgrid);    
        data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid - history.fourDaysAgo[0].fromgrid - history.fiveDaysAgo[0].fromgrid - history.sixDaysAgo[0].fromgrid;  
        history.kwhsSevenDaysAgo = data;
        res.json(history); 
        console.log(history);// return all in JSON format
    });

});

I do not understand why history.kwhsDayAgo[0].fromgrid on the fourDaysAgo query has not been set from the previous code and if not a mongoose error should have been sent back to the req. And as I already said the code works when day 4 -7 is commented out. I feel like there could be a more efficient way of achieving this but I am yet to find anyone who has posted a similar problem. I'd appreciate any help.

1
  • Make use of the Async module Commented Apr 7, 2015 at 6:04

1 Answer 1

1

You should use the Async module to populate the history object.

Install the module

npm install async

First require the module in the file

var Async = require('async');

Then in the request handler:

var history = {

    kwhsNow: function (callback) {
        kwhsNowQuery = eagleData.eagleKwhs.find(),
          kwhsNowQuery.sort('-_id');
          kwhsNowQuery.limit(1);
          kwhsNowQuery.exec(function(err, data) {
            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err)

            callback(null, data);
        });
    }, 

    kwhsToday: function (callback) {
        var sinceToday = moment().hours(0).minutes(0).seconds(0).format('x');

        var sinceTodayQuery = eagleData.eagleKwhs.find();
          sinceTodayQuery.where('_id').gte(sinceToday - 10000).lte(sinceToday + 10000); 
          sinceTodayQuery.limit(1);
          sinceTodayQuery.exec(function(err, data) {
            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Since today: ',data[0].fromgrid);  
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid;  
            callback (null, data);

        });
    }, 

    kwhsDayAgo: function (callback) {
        var dayAgo = moment().subtract(1, 'days').hours(0).minutes(0).seconds(0).format('x');

        var dayAgoQuery = eagleData.eagleKwhs.find();
          dayAgoQuery.where('_id').gte(dayAgo - 10000).lte(dayAgo + 10000); 
          dayAgoQuery.limit(1);
          dayAgoQuery.exec(function(err, data) {
            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Day Ago: ',data[0].fromgrid);    
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid;  
            callback (null, data);
            res.json(history); 
            console.log(history);// return all in JSON format       
        }); 
    }, 

    kwhsTwoDaysAgo: function (callback) {
        var twoDaysAgo = moment().subtract(2, 'days').hours(0).minutes(0).seconds(0).format('x');

        var twoDaysAgoQuery = eagleData.eagleKwhs.find();
        twoDaysAgoQuery.where('_id').gte(twoDaysAgo - 10000).lte(twoDaysAgo + 10000); 
        twoDaysAgoQuery.limit(1);
        twoDaysAgoQuery.exec(function(err, data) {
        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Two Days Ago: ',data[0].fromgrid);    
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid;  
            callback (null, data);

        });

    }, kwhsThreeDaysAgo: function (callback) {
            var threeDaysAgo = moment().subtract(3, 'days').hours(0).minutes(0).seconds(0).format('x');

          var threeDaysAgoQuery = eagleData.eagleKwhs.find();
          threeDaysAgoQuery.where('_id').gte(threeDaysAgo - 10000).lte(threeDaysAgo + 10000); 
          threeDaysAgoQuery.limit(1);
          threeDaysAgoQuery.exec(function(err, data) {
            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Three Days Ago: ',data[0].fromgrid);    
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid;  
            callback (null, data);
        });

    }, kwhsFourDaysAgo: function (callback) {
            var fourDaysAgo = moment().subtract(4, 'days').hours(0).minutes(0).seconds(0).format('x');    

          var fourDaysAgoQuery = eagleData.eagleKwhs.find();
          fourDaysAgoQuery.where('_id').gte(fourDaysAgo - 10000).lte(fourDaysAgo + 10000); 
          fourDaysAgoQuery.limit(1);
          fourDaysAgoQuery.exec(function(err, data) {
             //if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Four Days Ago: ',data[0].fromgrid);                    //history.kwhsToday[0].fromgrid -
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid;  
            callback (null, data);
        });
    }, kwhsFiveDaysAgo: function (callback) {
        var fiveDaysAgo = moment().subtract(5, 'days').hours(0).minutes(0).seconds(0).format('x');    

      var fiveDaysAgoQuery = eagleData.eagleKwhs.find();
          fiveDaysAgoQuery.where('_id').gte(fiveDaysAgo - 10000).lte(fiveDaysAgo + 10000); 
          fiveDaysAgoQuery.limit(1);
          fiveDaysAgoQuery.exec(function(err, data) {
            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Five Days Ago: ',data[0].fromgrid);    
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid - history.fourDaysAgo[0].fromgrid;  
            callback (null, data);
        });
    }, 

    kwhsSixDaysAgo: function (callback) {

        var sixDaysAgo = moment().subtract(6, 'days').hours(0).minutes(0).seconds(0).format('x');    

      var sixDaysAgoQuery = eagleData.eagleKwhs.find();
          sixDaysAgoQuery.where('_id').gte(sixDaysAgo - 10000).lte(sixDaysAgo + 10000); 
          sixDaysAgoQuery.limit(1);
          sixDaysAgoQuery.exec(function(err, data) {
            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Six Days Ago: ',data[0].fromgrid);    
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid - history.fourDaysAgo[0].fromgrid - history.fiveDaysAgo[0].fromgrid;  
            callback (null, data);
        });
    }, 

    kwhsSevenDaysAgo: function (callback){
        var sevenDaysAgo = moment().subtract(7, 'days').hours(0).minutes(0).seconds(0).format('x');    

      var sevenDaysAgoQuery = eagleData.eagleKwhs.find();
          sevenDaysAgoQuery.where('_id').gte(sevenDaysAgo - 10000).lte(sevenDaysAgo + 10000); 
          sevenDaysAgoQuery.limit(1);
          sevenDaysAgoQuery.exec(function(err, data) {
            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                return callback(err);

            console.log('Seven Days Ago: ',data[0].fromgrid);    
            data[0].fromgrid = history.kwhsNow[0].fromgrid - data[0].fromgrid - history.kwhsToday[0].fromgrid - history.kwhsDayAgo[0].fromgrid - history.twoDaysAgo[0].fromgrid - history.threeDaysAgo[0].fromgrid - history.fourDaysAgo[0].fromgrid - history.fiveDaysAgo[0].fromgrid - history.sixDaysAgo[0].fromgrid;  
            callback (null, data);
            res.json(history); 
            console.log(history);// return all in JSON format
        });
    } 
};

Async.parallel (history, function (err, results) {

    if (err)
        throw err;

    //results holds the data in object form
    console.log(results);

});

EDIT: Async.Parallel executes the functions passed to it simultaneously. If you want to have them executed one after the other, use Async.Series. This way, you will be able to access the results returned by the previous functions as well. However, you will have to pass the functions in an array instead of an object.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the fast response. I have been reading up on the async module. I have updated the code but each function is still being fired async which means I run into the same issue when manipulating the data in order I have written the code. When I comment out the calculations (subtractions) the object is populated but not in order.
{ kwhsNow: [ { _id: 1428426599000, fromgrid: 54137719 } ], kwhsFourDaysAgo: [ { _id: 1428044400000, fromgrid: 54022614 } ], kwhsToday: [ { _id: 1428390000000, fromgrid: 54123738 } ], kwhsFiveDaysAgo: [ { _id: 1427958000000, fromgrid: 53997075 } ], kwhsDayAgo: [ { _id: 1428303600000, fromgrid: 54092976 } ], kwhsSixDaysAgo: [ { _id: 1427871602000, fromgrid: 53975853 } ], kwhsTwoDaysAgo: [ { _id: 1428217200000, fromgrid: 54063325 } ], kwhsSevenDaysAgo: [ { _id: 1427785200000, fromgrid: 53954110 } ], kwhsThreeDaysAgo: [ { _id: 1428156300000, fromgrid: 54048604 } ] }
I assume this is the nature of how node works and each db query returns at different times which explains why kwhsToday is undefined in the kwhsFourDaysAgo function. I will remove my calcs from each function and manipulate the data at the end.
Yes. Node is designed to be used Asynchronously. Instead of Parallel, use Async.Series. This will execute the the functions one after the other. You will be able to access the values gathered in previous queries as well.
However, you will have to put these functions in an array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.