Mongo queries from node.js

You have a Mongo collection that you want to run a standard find on. Create a generic query worker (even the name isn’t exciting) to do the hard work while you simply pass in the name of the collection, the query to run and some optional options if you’re looking for more excitement. First I’ll show the query code then following that is an example of using it.

//Generic worker function to run a find query
exports.runQuery = function(myCollection, query, options, nextFn) {

    // perform the {query} on the collection and invoke the nextFn when done
    var db = new Db(dbname, new Server(host, port, {}), {native_parser:false});
    //console.log("host is " + host);
    db.open(function(err, db) {
        //console.log("reading mongo collection " + myCollection.toString());
        db.collection(myCollection, function(err, collection) {

            var optionsArray = {};
            if (typeof(options) != 'undefined') {
                optionsArray = options;
            } else {
                optionsArray['limit'] = 100;
                optionsArray['sort'] = {};
                optionsArray['sort']['_id']= -1;
            }

            optionsArray['slaveOk'] = true;

            collection.find(query, optionsArray, function (err, cursor){
                if (err) {
                    console.log("error is: " + err);
                }
                cursor.toArray(function(err, docs) {
                    console.log("found " + docs.length + " documents in " + myCollection);
                    var queryResults = [];
                    for(var i=0; i<docs.length; i++) {
                        queryResults[queryResults.length] = docs[i];
                    }
                    db.close();
                    nextFn(queryResults);
                });
            });
        });
    });
}

Calling the Query

Here we want up to 300 applications whose appId is neither sweetAppId1 or sweeterAppId2.  In the optionArray we ask nicely that it sorts them descending on the _id so we get most recent 300.

 queryParams['appId'] = {};
 queryParams['appId']['$nin'] = {};
 queryParams['appId']['$nin'] = ['sweetAppId1', 'sweeterAppId2'];

 var optionsArray = {};
 optionsArray['slaveOk'] = true;
 optionsArray['limit'] = 300;
 optionsArray['sort'] = {};
 optionsArray['sort']['_id']= -1;

 this.runQuery('appUsage', queryParams, optionsArray, function(results) {
      nextFn(results);
 });
Advertisements

Mongo grouping with node.js

Grouping in Mongo is equivalent to doing a GROUP BY in SQL. In this example we will be grouping within the Application collection. There are two bits of code here. First, it is the generic worker method that executes the grouping. It takes in all the parameters such as the key to group by and the reduce method to run and returns the results as JSON.

//Generic worker function to run a 'group by'
exports.runGroup = function(myCollection, inputKey, inputCond, inputInitial, inputReduce, options, nextFn) {

    // perform the {query} on the collection and invoke the nextFn when done
    var db = new Db(dbname, new Server(host, port, {}), {native_parser:false});

    db.open(function (error, client) {
      if (error) throw error;

      db.collection(myCollection, function(err, collection) {
          collection.group(
              inputKey, // key
              inputCond, // cond
              inputInitial,  // initial
              inputReduce, // reduce function
              true, // use the group command
              function(err, results){ 
                  nextFn(results);
              }
         );  // end of collection.group
      }); //end of db.collection
    });  //end of db.open
}

Second, we call the method on the Application collection to group by appId.

	var inputKey = { "appId" : true} ;
	var inputCond = { "timestamp" : { $gte: req.fromDate, $lte: req.toDate } };
	var inputReduce = "function(obj, prev) { prev.count++; }";
	var inputInitial =  { "count" : 0};
	var optionsArray = {};
	optionsArray['slaveOk'] = true;
	optionsArray['limit'] = 300;
	optionsArray['sort'] = {};
	optionsArray['sort']['_id']= -1;

	this.runGroup('restCall', inputKey, inputCond, inputInitial, inputReduce, optionsArray, function(results) {

		results.sort(function(a,b) {
		    // this sorts the array using the total count of the 'count' column
    		    return ((a['count']  b['count']) ? -1 : 0));
		});

		nextFn(results);
	});