Definition
Compatibility
You can use $sort for deployments hosted in the following
environments:
MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
MongoDB Enterprise: The subscription-based, self-managed version of MongoDB
MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB
Syntax
The $sort stage has the following prototype form:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
$sort takes a document that specifies the field(s) to
sort by and the respective sort order. <sort order> can have one
of the following values:
Value | Description |
|---|---|
| Sort ascending. |
| Sort descending. |
|
|
If sorting on multiple fields, sort order is evaluated from left to
right. For example, in the form above, documents are first sorted by
<field1>. Then documents with the same <field1> values are
further sorted by <field2>.
Behavior
Performance
$sort is a blocking stage, which causes the pipeline to wait for all
input data to be retrieved for the blocking stage before processing the
data. A blocking stage may reduce performance because it reduces
parallel processing for a pipeline with multiple stages. A blocking
stage may also use substantial amounts of memory for large data sets.
Limits
You can sort on a maximum of 32 keys.
Providing a sort pattern with duplicate fields causes an error.
Sort Consistency
MongoDB does not store documents in a collection in a particular order. When sorting on a field which contains duplicate values, documents containing those values may be returned in any order.
The $sort operation is not a "stable sort," which means that documents
with equivalent sort keys are not guaranteed to remain in the same relative
order in the output as they were in the input.
If the field specified in the sort criteria does not exist in two documents, then the value on which they are sorted is the same. The two documents may be returned in any order.
If consistent sort order is desired, include at least one field in your
sort that contains unique values. The easiest way to guarantee this is
to include the _id field in your sort query.
Consider the movies collection in the sample_mflix sample
dataset. The following command uses the $sort stage to
sort movies released in 1925 or 1926 by year in ascending order:
db.movies.aggregate( [ { $match: { year: { $in: [ 1925, 1926 ] } } }, { $sort: { year: 1 } }, { $project: { _id: 0, title: 1, year: 1 } } ] )
In this example, sort order may be inconsistent, since the year
field contains duplicate values for both 1925 and 1926.
The operation returns documents in ascending order by year, but the order
of documents with duplicate values for year might not be the same
across multiple executions of the same sort. For example, here are
the results from two different executions of the above command:
[ { title: "Clash of the Wolves", year: 1925 }, { title: "Lady Windermere's Fan", year: 1925 }, { title: "Grass: A Nation's Battle for Life", year: 1925 }, { title: "Beau Geste", year: 1926 }, { title: "The Black Pirate", year: 1926 }, { title: "Ella Cinders", year: 1926 }, { title: "For Heaven's Sake", year: 1926 }, { title: "The Son of the Sheik", year: 1926 }, { title: "The Strong Man", year: 1926 } ]
[ { title: "Lady Windermere's Fan", year: 1925 }, { title: "Grass: A Nation's Battle for Life", year: 1925 }, { title: "Clash of the Wolves", year: 1925 }, { title: "The Strong Man", year: 1926 }, { title: "The Black Pirate", year: 1926 }, { title: "Ella Cinders", year: 1926 }, { title: "Beau Geste", year: 1926 }, { title: "The Son of the Sheik", year: 1926 }, { title: "For Heaven's Sake", year: 1926 } ]
While the operation sorts values for year in ascending order,
the order of the documents containing duplicate values for year
(i.e. 1925 and 1926) is not the same.
To achieve a consistent sort, add a field which contains exclusively
unique values to the sort. The following command uses the
$sort stage to sort on both the year field and the
_id field:
db.movies.aggregate( [ { $match: { year: { $in: [ 1925, 1926 ] } } }, { $sort: { year: 1, _id: 1 } } ] )
Since the _id field is always guaranteed to contain exclusively
unique values, the returned sort order will always be the same across
multiple executions of the same sort.
Sort by an Array Field
When MongoDB sorts documents by an array-value field, the sort key depends on whether the sort is ascending or descending:
In an ascending sort, the sort key is the lowest value in the array.
In a descending sort, the sort key is the highest value in the array.
The query filter does not affect sort key selection.
For example, consider these documents from the movies collection
in the sample_mflix sample dataset:
{ _id: ObjectId("573a1395f29313caabce166c"), title: "The Comancheros", genres: [ "Action", "Western", "Adventure" ] } { _id: ObjectId("573a1391f29313caabcd8521"), title: "The Son of the Sheik", genres: [ "Adventure", "Drama" ] }
The following queries sort the documents by the genres field in
ascending and descending order:
// Ascending sort db.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: 1 } } ] )
// Descending sort db.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: -1 } } ] )
Both of the preceding queries return The Comancheros first because
Action and Western are the lowest and highest entries in its
genres array, respectively.
Filter and Sort by an Array Field
When you filter and sort by a field that contains an array, the filter does not affect the value used as the sort key. The sort always considers all array values as potential sort keys.
For example, the following query finds movies whose genres array
includes "Drama" or "Western" and sorts the results by
genres in ascending order:
db.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] }, genres: { $in: [ "Drama", "Western" ] } } }, { $sort: { genres: 1 } } ] )
The sort is ascending. The sort key is the first value in the genres array
when sorted alphabetically:
In
The Comancheros, the firstgenreselement isAction. This value is used as the sort key even though it does not match the filter{ genres: { $in: [ "Drama", "Western" ] } }.In
The Son of the Sheik, the firstgenreselement isAdventure. Similarly, this operation usesAdventureas the sort key even though it does not match the filter.
The query returns The Comancheros first.
Tip
Sort only by Matched Values
To only consider matched values as potential sort keys, you can generate a new field containing the matched values and sort on that field. For more information, see these pipeline stages and expressions:
$sort Operator and Memory
$sort + $limit Memory Optimization
When a $sort precedes a $limit and there are no
intervening stages that modify the number of documents, the optimizer can
coalesce the $limit into the $sort. This allows
the $sort operation to only
maintain the top n results as it progresses, where n is the
specified limit, and ensures that MongoDB only needs to store n items in memory.
This optimization still applies when allowDiskUse is true and
the n items exceed the aggregation memory limit.
Optimizations are subject to change between releases.
$sort and Memory Restrictions
Pipeline stages that require more than 100 megabytes of memory to execute write temporary files to disk by default. These temporary files last for the duration of the pipeline execution and can influence storage space on your instance.
Individual find and aggregate commands can override the
allowDiskUseByDefault parameter by either:
Using
{ allowDiskUse: true }to allow writing temporary files out to disk whenallowDiskUseByDefaultis set tofalseUsing
{ allowDiskUse: false }to prohibit writing temporary files out to disk whenallowDiskUseByDefaultis set totrue
Note
For MongoDB Atlas, it is recommended to configure storage auto-scaling to prevent long-running queries from filling up storage with temporary files.
If your Atlas cluster uses storage auto-scaling, the temporary files may cause your cluster to scale to the next storage tier.
For additional details, see Aggregation Pipeline Limits.
$sort Operator and Performance
The $sort operator can take advantage of an index if it's
used in the first stage of a pipeline or if it's only preceded by a
$match stage.
When you use the $sort on a sharded cluster, each shard
sorts its result documents using an index where available. Then the
mongos or one of the shards performs a streamed merge
sort.
Examples
The examples on this page use data from the sample_mflix sample dataset. For details on how to load this dataset into your self-managed MongoDB deployment, see Load the sample dataset. If you made any modifications to the sample databases, you may need to drop and recreate the databases to run the examples on this page.
Ascending/Descending Sort
For the field or fields to sort by, set the sort order to 1 or -1 to
specify an ascending or descending sort respectively, as in the following example:
db.movies.aggregate( [ { $sort: { year: -1, title: 1 } }, { $limit: 5 } ] )
This operation sorts the documents in the movies collection in
descending order by the year field and then in ascending order by the
value in the title field, returning the first five results.
When comparing values of different BSON types in sort operations, MongoDB uses the following comparison order, from lowest to highest:
MinKey (internal type)
Null
Numbers (ints, longs, doubles, decimals)
Symbol, String
Object
Array
BinData
ObjectId
Boolean
Date
Timestamp
Regular Expression
JavaScript Code
JavaScript Code with Scope
MaxKey (internal type)
For details on the comparison/sort order for specific types, see Comparison/Sort Order.
Text Score Metadata Sort
Note
$text provides text query capabilities for self-managed
(non-Atlas) deployments. For data hosted on MongoDB, MongoDB also
offers an improved full-text query solution, MongoDB Search.
The following example uses the movies collection in the
sample_mflix sample dataset. Before running it, create a
text index on the plot field:
db.movies.createIndex( { plot: "text" } )
For a pipeline that includes $text, you can sort by
descending relevance score using the { $meta: "textScore"
} expression. In the { <sort-key> } document, set the
{ $meta: "textScore" } expression to an arbitrary
field name. The field name is ignored by the query system. For example:
db.movies.aggregate( [ { $match: { $text: { $search: "pirate" } } }, { $sort: { score: { $meta: "textScore" }, year: -1 } }, { $limit: 5 } ] )
This operation uses the $text operator to match the documents,
and then sorts first by the "textScore" metadata in descending
order, and then by the year field in descending order. The
score field name in the sort document is ignored by the query
system. The pipeline returns the first five results. In this
pipeline, the projection does not include the "textScore" metadata and
does not return the metadata as part of the matching documents. See
$meta for more information.
The following Movie class models the documents in the sample_mflix.movies
collection:
public class Movie { public ObjectId Id { get; set; } public int Runtime { get; set; } public string Title { get; set; } public string Rated { get; set; } public List<string> Genres { get; set; } public string Plot { get; set; } public ImdbData Imdb { get; set; } public int Year { get; set; } public int Index { get; set; } public string[] Comments { get; set; } [] public DateTime LastUpdated { get; set; } }
Note
ConventionPack for Pascal Case
The C# classes on this page use Pascal case for their property names, but the
field names in the MongoDB collection use camel case. To account for this difference,
you can use the following code to register a ConventionPack when your
application starts:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
To use the MongoDB .NET/C# driver to add a $sort stage to an aggregation
pipeline, call the Sort() method on a PipelineDefinition object.
The following example creates a pipeline stage that sorts the input Movie documents first in descending order by the Year
field, then in ascending order by the Title field:
var pipeline = new EmptyPipelineDefinition<Movie>() .Sort(Builders<Movie>.Sort.Combine( Builders<Movie>.Sort.Descending(m => m.Year), Builders<Movie>.Sort.Ascending(m => m.Title)));
To use the MongoDB Node.js driver to add a $sort stage to an aggregation
pipeline, use the $sort operator in a pipeline object.
The following example creates a pipeline stage that sorts the input movie documents first in descending order by the year
field, and then in ascending order by the title field. The
example then runs the aggregation pipeline:
const pipeline = [{ $sort: { year: -1, title: 1 } }]; const cursor = collection.aggregate(pipeline); return cursor;
Learn More
To see full aggregation examples that use the $sort stage, see the
Complete Aggregation Pipeline Tutorials.