BumbleGee
BumbleGee

Reputation: 2031

RangeError when trying to execute mongodb query with mongoose/mongodb-native

I have a problem which has already cost me a couple of days and I totally fail to understand it. I use node.js and have a mongodb with places indexed for their coordinates. I verified that the index works fine beforehand. For a set of coordinates, I want to find the nearest place. Here's how I tried to go about it:

    var Places = require(./models/places.js),
        coordFinder = require('./coordFinder.js');

    ...

    function getCoords(userId, callback) {
       coordFinder.getCoords(userId, function(err, coords) {
          if (err) {
             callback(err);
          } else {   
             callback(null, coords);
          }
       }
    }

    function getNearestPlaces(coords, callback) {
       async.forEachSeries(
          coords,
          function(coord, done) {
             Places.findOne(
                { coordinates: { $near: [ coord.lat, coord.lon ] } },
                function(err, place) {
                   // do something with place
                   done();
                }
             )
          },
          function(err) {
             callback(err ? err : null);    
          }
       );
    }

    ...

    async.waterfall(
       [
          ...
          getCoords,
          getNearestPlaces,
          ...
       ],
       function(err) {
          ...
       }
    }

The mongodb query consistently fails with the following error message for the first query:

RangeError: Maximum call stack size exceeded

When I change the query in getNearestPlaces to

... { $near: [ 10, 10 ] } ...

I as consistently get no error and the correct place. The same happens if I avoid the call to coordFinderin getCoords and change getCoords to

function getCoords(userId, callback) {
    callback(
        null, 
        [ 
           // some coordinates
        ]
    );

I know the error indicates a stack overflow (increasing the stack size didn't help) but I can't figure out how I could have caused one. Does anyone have a clue as to why this happens? Thanks in advance for your insights!

Edit: It got the same problem when using mongodb-native directly, by the way, so mongoose seems not to be the problem. One more clue - using the same query never gives me a problem when I don't call it from within a callback. Could that be a source of error?

I use

Cheers, Georg

Upvotes: 1

Views: 637

Answers (2)

BumbleGee
BumbleGee

Reputation: 2031

mjhm pointed me in the right direction. Apparently, the Number instanced passed to the mongoose query caused the stack overflow. I'm not sure why, but creating a new Number object from the old one (as mjhm suggested) or converting the number into a primitive with valueOf() solved the problem.

If anyone has a clue as to how the original Number object caused the stack overflow, I'd very much appreciate any insights you might have to offer.

Upvotes: 1

mjhm
mjhm

Reputation: 16695

The problem is most likely coming from the hidden recursion of async.forEachSeries. Try wrapping the Places.findOne call with setTimeout like this:

function getNearestPlaces(coords, callback) {
   async.forEachSeries(
      coords,
      function(coord, done) {
         setTimeout(function () {
             Places.findOne(
                 { coordinates: { $near: [ coord.lat, coord.lon ] } },
                 function(err, place) {
                     // do something with place
                     done();
                 }
             );
         }, 1);
      },
      function(err) {
         callback(err ? err : null);    
      }
   );
}

This puts the Places.findOne call outside of the call stack of async.forEachSeries.

Upvotes: 2

Related Questions