1

I'm new to JS in general, but I am trying to query some data from MongoDB. Basically, my first query retrieves information for the session with the specified session id. The second query does a simple geospacial query for documents with a location near the specified location.

I'm using the mongodb-native javascript driver. All of these query methods return their results in callbacks, so they're non-blocking. This is the root of my troubles. What I'm needing to do is retrieve the results of the second query, and create an Array of sessionIds of all the returned documents. Then I'm going to pass those to a function later. But, I can't generate this array and use it anywhere outside the callback.

Does anyone have any idea how to properly do this?

db.collection('sessions', function(err, collection) {
  collection.findOne({'sessionId': client.sessionId}, function(err, result) {
    collection.find({'geolocation': {$near: [result.geolocation.latitude, result.geolocation.longitude]}}, function(err, cursor) {
      cursor.toArray(function(err, item) {

      console.log(item);
    });
  });
});

2 Answers 2

6

Functions are the only thing on javascript that "enclose" scope.

This means that the variable items in your inner callback function are not accessible on the outer scope.

You can define a variable in the outer scope so it will be visible to all the inner ones:

function getItems(callback) {
  var items;

  function doSomething() {
    console.log(items);
    callback(items);
  }

  db.collection('sessions', function(err, collection) {
    collection.findOne({'sessionId': client.sessionId}, function(err, result) {
      collection.find({'geolocation': {$near: [result.geolocation.latitude, result.geolocation.longitude]}}, function(err, cursor) {
        cursor.toArray(function(err, docs) {
          items = docs;
          doSomething();
         });
       });
     });
   });
}
Sign up to request clarification or add additional context in comments.

Comments

0

Node.js is asynchronous, so your code should be written to match it.

I've found this model useful. Each nested callback jumble is wrapped in helper function that calls the argument callback 'next' with error code and result.

function getSessionIds( sessionId, next ) {
    db.collection('sessions', function(err, collection) {
      if (err) return next(err);
      collection.findOne({sessionId: sessionId}, function(err, doc) {
          if (err) return next(err);
          if (!doc) return next(false);
          collection.find({geolocation: {$near: [doc.geolocation.latitude, result.geolocation.longitude]}}.toArray(function(err, items) {
              return next(err, items);
          });
      });
    });
}

Then in your calling code

getSessionIds( someid, _has_items);
function _has_items(err, items) {
   if( err ) // failed, do something
   console.log(items);
}

Comments

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.