Sling Academy
Home/Node.js/Sorting results in Mongoose (ASC and DESC)

Sorting results in Mongoose (ASC and DESC)

Last updated: December 30, 2023

Overview

Sorting queries is a fundamental aspect of working with databases. When using MongoDB with Mongoose in a Node.js environment, sorting results can be straightforward yet powerful for organizing your query returns. In this tutorial, we will cover how you can implement ascending and descending sort operations on your dataset using Mongoose and dive into more advanced scenarios to showcase how sorting can be used effectively.

Basic Sorting

Let’s begin with the basics. To sort documents in ascending or descending order using Mongoose, you can leverage the .sort() function, which can be chained after your query construction. Considering the usage of modern JavaScript and ES modules, let’s assume we have a model User:

import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
  username: String,
  createdAt: Date
});
const User = mongoose.model('User', userSchema);

To sort the users by creation date in ascending order:

User.find().sort({ createdAt: 'asc' }).exec();

And for descending order:

User.find().sort({ createdAt: 'desc' }).exec();

Sorting by Multiple Fields

Often, you may want to sort by more than one field. For instance, you may want users to be sorted by last name and then by first name, both in ascending order:

User.find().sort({ lastName: 'asc', firstName: 'asc' }).exec();

Using Sort With Select

You can also combine the .sort() with .select() to control which fields you want to retrieve from the documents:

User.find().sort({ createdAt: -1 }).select('username createdAt').exec();

Complex Sorting In Aggregations

When performing more elaborate queries using the aggregation framework, sorting fits right in as one of the pipeline stages. Here’s an example of sorting within an aggregation:

import mongoose from 'mongoose';

// Some more complex query
const ageAvgPerCountry = await User.aggregate([
  {
    $group: {
      _id: '$country',
      averageAge: { $avg: '$age' }
    }
  },
  {
    $sort: { averageAge: 1 }
  }
]);

Pagination and Sorting

Pagination often goes hand in hand with sorting. If you’re looking to display results in a paginated fashion, you’ll need to consider the sort order for consistency across pages. Here’s how you can do pagination with sorting:

const page = 1;
const limit = 10;

User.find()
  .sort({ createdAt: -1 })
  .skip((page - 1) * limit)
  .limit(limit)
  .exec();

Note: For production-grade pagination, you’ll want to look into more robust cursor-based pagination strategies.

Sorting with Custom Parameters

In real-world applications, you likely need to sort queries based on client inputs dynamically. For security and functionality, avoid directly passing client input to your sort methods. Here’s a method for implementing a safe, flexible sorting mechanism:

// a map of allowed sort fields
const sortables = { username: 'username', createdAt: 'createdAt' };
let sortBy = clientInput.sortBy;
let sortOrder = clientInput.sortOrder === 'asc' ? 1 : -1;

sortBy = sortables[sortBy] || 'defaultField';

User.find().sort({ [sortBy]: sortOrder }).exec();

Remember to sanitize and validate clientInput accordingly.

Conclusion

Sorting is an integral part of querying databases, and when using Mongoose, it can be extremely robust yet user-friendly. By mastering the sorting mechanisms that Mongoose offers, you can create everything from straightforward alphabetical listings through to more complex, multiple-field, and multi-directional sorts to fulfil any application’s requirement. Always remember to sanitize and validate any user input you use to shape queries, including sorting parameters. Armed with these techniques, your data will be displayed just as needed for the best user and developer experience.

Next Article: Sorting results in Mongoose by date

Previous Article: How to Implement Pagination in Mongoose

Series: Mongoose.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates