Search code examples
node.jsmongodbexpressmongoskin

MongoDB query criterias and projections


I'm bulding an app using Node/Express/MongoDB/Mongoskin.

I the database I have a collection namned "clients", where documents containing information about client account. Each client document contains an array that contains invoice-objects, like this:

doc.invoices = [
  {year: 2012,
  quarter: 1, 
  daily: 912.00, 
  sms: 42.00, 
  paid: true},

  {year: 2012,
  quarter: 2, 
  daily: 913.00, 
  sms: 55.00, 
  paid: true}, 

  {year: 2012,
  quarter: 3, 
  daily: 876.00, 
  sms: 82.00, 
  paid: true}, 

  {year: 2012,
  quarter: 4, 
  daily: 903.00, 
  sms: 93.00, 
  paid: false},

  {year: 2013,
  quarter: 1, 
  daily: 915.00, 
  sms: 67.00, 
  paid: true},

  {year: 2013,
  quarter: 2, 
  daily: 920.00, 
  sms: 35.00, 
  paid: true}, 

  {year: 2013,
  quarter: 3, 
  daily: 880.00, 
  sms: 92.00, 
  paid: true}, 

  {year: 2013,
  quarter: 4, 
  daily: 900.00, 
  sms: 85.00, 
  paid: false}
]

Question: Lets say i want to query ALL documents from this collection, like in a Superadmin-view showing all clients, but i want to limit the information returned from the invoice-array to objects where "year" is equal to a certain value, for example 2013, current year.

I guess projections is what I need, but the problem is that the projection is only returning the first result it finds...


Solution

  • first of all, projection does not return the first result it finds it tells mongo what to return.

    .findOne(query) will LIMIT result to one or find(query).limit(1) will also do the same.

    You say you are trying to "get all" your data.

    a standard find type query will get your started...

    find({mongo:query},{mongo:projection})
    

    but limits results to a cursor from the mongo shell*

    since you said your using express.js you can use a javascript function to "return all" the results of a simple find like this one...

    db.sales.find({"year":2013},{_id:0,"year":1,"quarter":1,"daily":1,"sms":1,"paid":1}) 
    

    by first setting up a route to a function

    app.get('/sales/yr/:yr', sales.getAllResults);
    

    and then a function to handle your simple mongo query and projection.

    /**
     *  get ALL results given YEAR ONLY
     *  extend jsonQuery to modify results
     *  extend or reduce jsonProjection to control data returned
     */
    exports.getAllResults= function(req, res) {
        var yr = req.params.yr ;    
        var jsonQuery = {"year":yr} ;  //add or remove comma seperated "key":values given your JSON collection
        var jsonProjection = {_id:0,"year":1,"quarter":1,"daily":1,"sms":1,"paid":1} ; //leave year out since that's specified in the query anyhow
        var jsort = {"some-thing-else":-1} ; //-1 descending or 1 ascending
        db.collection("YOUR-COLLECTION_NAME", function(err, collection) {
            collection.find( jsonQuery, jsonProjection).sort(jsort).toArray( function(err, items) {
                res.send(items);
            });
        });
    }
    

    finally you might want to follow a tutorial for express and mongo there are some good ones, I put this answer together based on an excellent starter from Chris Coenraets see:-

    http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/

    • with a standard mongo query shell you are limited to paged result set by default, where typing "it" will iterate through the results.