How to extend Query object in mongoose

Problem

I'be trying to add a chain method to the Query object called "paginate". If I add it to query.js I can use it without any problems. However, it's not a good idea to modify one of the core files.

I'm using this code I found with some modifications and want it to be part of the Query prototype, but I haven't had any success on making it work out of Query.js.

How can I accomplish this? Are there any docs on how to extends any of these core files through a module? I haven't found anything that works for me.

mongoose.Query.prototype.paginate = function(page, limit, cb) {
  var model, query, skipFrom;
  if (page == null) {
    page = 1;
  }
  if (limit == null) {
    limit = 10;
  }
  query = this;
  model = this.model;
  skipFrom = (page * limit) - limit;
  query = query.skip(skipFrom).limit(limit);
  if (cb) {
    return query.run(function(err, docs) {
      if (err) {
        return cb(err, null, null);
      } else {
        return model.count(query._conditions, function(err, total) {
          return cb(null, total, docs);
        });
      }
    });
  } else {
    throw new Error("pagination needs a callback as the third argument.");
  }
};
Problem courtesy of: markitusss

Solution

Turns out it was a lot easier than what I expected. This is what I did and it worked:

Created a paginate.js file with:

mongoose = require('mongoose');

mongoose.Query.prototype.paginate = function(aPageStart, aLimit, aCallback) {
  var model, query;

  if (aLimit == null) {
    aLimit = 10;
  }
  query = this;
  model = this.model;
  query = query.skip(aPageStart).limit(aLimit);
  if (aCallback) {
    return query.run(function(aError, aDocs) {
      if (aError) {
        return aCallback(aError, null, null);
      } else {
        return model.count(query._conditions, function(aError, aTotal) {
          return aCallback(null, aTotal, aDocs);
        });
      }
    });
  } else {
    throw new Error("pagination needs a callback as the third argument.");
  }
};

and just require it where needed (In my model in this case).

Then you can call this method as the last of the chain.

Cheers,

Marcos.

Solution courtesy of: markitusss

Discussion

Maybe you can use this module or look how they achieve it: mongoose-paginate

Another solution is to create a method to your schema like that:

Schema.statics.paginate = (page, limit, cb) ->
   ...
  return query;
// or
Schema.statics.paginate = (query, page, limit, cb) ->
   ...
  return query.exec();
Discussion courtesy of: Charles

This recipe can be found in it's original form on Stack Over Flow.