Query on top N rows in mongodb
Efficiently Querying Top N Rows in MongoDB

Learn how to retrieve the top N documents from a MongoDB collection based on specific criteria, covering various methods and best practices for performance.
When working with large datasets in MongoDB, a common requirement is to fetch only a subset of documents, specifically the 'top N' based on a certain sorting order. This is crucial for displaying leaderboards, recent activity feeds, or paginated results. This article will guide you through the most effective ways to achieve this using MongoDB's powerful query operators, focusing on performance and correctness.
Understanding the Core Concepts: Sort and Limit
The foundation for querying the top N rows in MongoDB lies in two fundamental aggregation pipeline stages (or query operators for simple cases): $sort
and $limit
. The $sort
stage arranges documents in a specified order, while the $limit
stage restricts the number of documents passed to the next stage or returned as results.
flowchart TD A[Start Query] --> B{Collection.find() or Aggregate()} B --> C{Apply Filtering (e.g., .find({query}))} C --> D{Apply Sorting (e.g., .sort({field: -1}))} D --> E{Apply Limiting (e.g., .limit(N))} E --> F[Return Top N Documents] F --> G[End Query]
Basic workflow for querying top N documents in MongoDB
The order of these operations is critical. You must sort the documents before limiting them to ensure you are getting the 'top' documents according to your criteria. If you limit first, you might accidentally discard documents that would have been part of your top N set after sorting.
Method 1: Using find()
with sort()
and limit()
For straightforward queries, the find()
method combined with sort()
and limit()
is the most common and efficient approach. This method is ideal when you don't need complex aggregations beyond filtering, sorting, and limiting.
db.products.find(
{ category: "electronics" } // Optional: filter documents
)
.sort( { price: -1, _id: 1 } ) // Sort by price descending, then _id ascending for tie-breaking
.limit(10); // Get the top 10 documents
Example of finding the top 10 most expensive electronics products
_id
, especially if the primary sort field might have duplicate values. This ensures a consistent and deterministic order for your 'top N' results.Method 2: Using the Aggregation Pipeline
When your 'top N' query involves more complex operations like grouping, calculating averages, or performing lookups before determining the top documents, the aggregation pipeline is the way to go. The $sort
and $limit
stages function similarly within the pipeline.
db.orders.aggregate([
{ $match: { status: "completed" } }, // Filter completed orders
{ $group: { _id: "$customerId", totalSpent: { $sum: "$amount" } } }, // Group by customer and sum their spending
{ $sort: { totalSpent: -1 } }, // Sort by total spending descending
{ $limit: 5 } // Get the top 5 customers by spending
]);
Example of finding the top 5 customers by total spending using aggregation
$sort
and $limit
after stages that reduce the number of documents (like $match
or $group
) can significantly improve performance by processing fewer documents.Performance Considerations and Indexing
For optimal performance, especially on large collections, indexing is crucial. An index on the field(s) used in your $sort
operation can drastically speed up queries. If you also filter documents using $match
(or find()
's query object), an index that covers both the filter and sort fields is even better.
// Create an index on 'category' and 'price' for the products collection
db.products.createIndex( { category: 1, price: -1 } );
// This index will efficiently support the query:
db.products.find({ category: "electronics" }).sort({ price: -1 }).limit(10);
Creating a compound index to optimize top N queries
category
and sort by price
, an index on { category: 1, price: -1 }
is highly effective.