3

Been messing around with the NodeJS + MongoDB + Express stack, and came across an issue with performing queries. I have some helper methods in my index.js file:

var mongoClient = new MongoClient(new Server(mongoHost, mongoPort)); //B
mongoClient.open(function(err, mongoClient) { //C
  if (!mongoClient) {
      console.error("Error! Exiting... Must start MongoDB first");
      process.exit(1); //D
  }
  var db = mongoClient.db("trackr");  //E
  collectionDriver = new CollectionDriver(db); //F
});

app.use(express.static(path.join(__dirname, 'public')));

app.get('/:collection', function(req, res) { //A
   var params = req.params; //B
   collectionDriver.findAll(req.params.collection, function(error, objs) { //C
          if (error) { res.send(400, error); } //D
          else { 
              if (req.accepts('html')) { //E
                  res.render('data',{objects: objs, collection: req.params.collection}); //F
              } else {
              res.set('Content-Type','application/json'); //G
                  res.send(200, objs); //H
              }
         }
    });
});

app.get('/:collection/:entity', function(req, res) { //I
   var params = req.params;
   var entity = params.entity;
   var collection = params.collection;
   if (entity) {
       collectionDriver.get(collection, entity, function(error, objs) { //J
          if (error) { res.send(400, error); }
          else { res.send(200, objs); } //K
       });
   } else {
      res.send(400, {error: 'bad url', url: req.url});
   }
});

app.get('/:collection/iata/:value', function(req, res) { //I
   console.log("entrou");
   var params = req.params;
   var value = params.value;
   var collection = params.collection;

   if (value) {
       collectionDriver.getByIata(collection, value, function(error, objs) { //J
          if (error) { res.send(400, error); }
          else { res.send(200, objs); } //K
       });
   } else {
      res.send(400, {error: 'bad url', url: req.url});
   }
});

Problem here is - whenever I point to the "/collection/" route through a GET request, everything works fine - all the items from the collection are rendered. Also, if I point to the "/collection/entity" route, by providing an ObjectID, the particular item is also returned. And when I try a GET request for the /collection/iata/value, no objects are returned. However, when I perform the same query in the MongoDB prompt, the document is returned successfully.

Whole Collection Query

collection_query

Query by ObjectID

query_objectID

Query by IATA Document Attribute

query_iata

Query directly through MongoDB Prompt

query_mongo

In my index.js, I'm calling the functions from collectionDriver.js, code excerpt below:

    CollectionDriver.prototype.findAll = function(collectionName, callback) {
    this.getCollection(collectionName, function(error, the_collection) { //A
      if( error ) callback(error);
      else {
        the_collection.find().toArray(function(error, results) { //B
          if( error ) callback(error);
          else callback(null, results);
        });
      }
    });
};

CollectionDriver.prototype.get = function(collectionName, param, callback) { //A
    console.log("Get by ObjectID");
    this.getCollection(collectionName, function(error, the_collection) {
        if (error) callback(error);
        else {
            var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); //B
            if (!checkForHexRegExp.test(param)) callback({error: "invalid id"});
            else the_collection.findOne({'_id':ObjectID(param)}, function(error,doc) { //C
                if (error) callback(error);
                else callback(null, doc);
            });
        }
    });
};

CollectionDriver.prototype.getByIata = function(collectionName, attribute, callback) { //A
    console.log('entrou no driver - encontrar por atributo - collectionName: ' + collectionName);
    this.db.collection(collectionName, function(error, the_collection) {
        if( error ) callback(error);
        else the_collection.find({'iata': attribute}, function(error, collection) {
            collection.count({}, function(error, numDocs){
                console.log(numDocs);
            });
        });
    });
};

I'm aware that ObjectID queries require conversion to BSON - am I missing some similar requirement when trying to query for a document's attribute?

Thanks in advance.

1
  • Are you sure that your routes don´t make a collision? Maybe /collection/iata/value matches with the /:collection/:entity route. Commented Aug 22, 2015 at 12:52

1 Answer 1

4

You are not returning anything from getByIata prototype

CollectionDriver.prototype.getByIata = function(collectionName, attribute, callback) { //A
    console.log('entrou no driver - encontrar por atributo - collectionName: ' + collectionName);
    this.db.collection(collectionName, function(error, the_collection) {
        if( error ) callback(error);
        else the_collection.find({'iata': attribute}, function(error, doc) {
            if (error) callback(error);
            else callback(null, doc);
        });
    });
};
Sign up to request clarification or add additional context in comments.

2 Comments

You were right, silly mistake. Replaced getByIata prototype for the code below and it worked:
CollectionDriver.prototype.getByIata = function(collectionName, attribute, callback) { //A console.log("Get by Iata"); this.getCollection(collectionName, function(error, the_collection) { if (error) callback(error); else { the_collection.findOne({'iata':attribute}, function(error,doc) { //C if (error) callback(error); else callback(null, doc); }); } }); };

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.