Is there a way to specify sorting order on the schema/model level in Mongoose?
I have model Posts
, and I always fetch posts ordered by 'createdAt'
field. Thus on each query I have to write .sort('-createdAt')
. Can I make this order default for this model?
There is no way, in Mongoose, directly to define a default sort order on your query.
If you're doing something over and over again though, you might want to abstract this into a function that does it for you:
function findPostsByDate(cb){
Posts.find({}).sort('-createdAt').exec(cb);
}
Or even something more generic than that:
function findXByDate(model, findCriteria, cb){
model.find(findCriteria).sort('-createdAt').exec(cb);
}
You can achieve this by creating a static method in your schema definition.
Mongoose documentation for Methods and statics here: http://mongoosejs.com/docs/2.7.x/docs/methods-statics.html
Example
In your schema file:
PostSchema.statics.sortedFind = function sortedFind(query, fields, options cb){
//First 3 parameters are optional
if( arguments.length === 1){
cb = query;
} else if (arguments.length === 2) {
cb = fields;
} else if(arguments.length === 3){
cb = options;
}
this.find(query, fields, options).sort('-createdAt').exec(cb);
}
Then you can use:
var query = {user_id: currentUser.id}; // query example, modify according to your needs
Post.sortedFind(query, function(err, response){ /* Your code goes here */ });
This is how I enforce sortable columns and provide a default sort. I copy this code into each model and just supply the allowSortOn array.
postSchema.pre('find', function (){
if (typeof this.options.sort !== 'undefined') {
var allowSortOn = ["_id","createdAt"] // add other allowable sort columns here
, propCount = 0;
for (var prop in this.options.sort)
if (this.options.sort.hasOwnProperty(prop)) {
if (allowSortOn.indexOf(prop) === -1) {
console.log('Invalid sort column ' + prop);
delete this.options.sort[prop];
} else {
propCount++;
}
}
if (propCount === 0) {
this.options.sort[allowSortOn[1]] = 1;
console.log('Setting sort column to ' + JSON.stringify(this.options.sort));
}
}
})