Database Manual / Reference / Query Language / Aggregation Stages

$sort (aggregation stage)(聚合阶段)

Definition定义

$sort
Sorts all input documents and returns them to the pipeline in sorted order.对所有输入文档进行排序,并按排序顺序将其返回到管道。

Compatibility兼容性

You can use $sort for deployments hosted in the following environments:您可以将$sort用于在以下环境中托管的部署:

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud:云中MongoDB部署的完全托管服务
  • MongoDB Enterprise: The subscription-based, self-managed version of MongoDB:MongoDB的基于订阅的自我管理版本
  • MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB:MongoDB的源代码可用、免费使用和自我管理版本

Syntax语法

The $sort stage has the following prototype form:$sort阶段具有以下原型形式:

{ $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:获取一个文档,该文档指定了要排序的字段和相应的排序顺序。<sort order>可以有以下值之一:

ValueDescription描述
1Sort ascending.升序排序。
-1Sort descending.降序排序。
{ $meta: "textScore" }Sort by the computed textScore metadata in descending order. See Text Score Metadata Sort for an example.按计算出的textScore元数据降序排序。示例请参见文本分数元数据排序

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>.如果对多个字段进行排序,则从左到右计算排序顺序。例如,在上面的表单中,文档首先按<field1>排序。然后,具有相同<field1>值的文档将按<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.您最多可以对32个键进行排序。
  • 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.MongoDB不会以特定顺序将文档存储在集合中。在对包含重复值的字段进行排序时,包含这些值的文档可以按任何顺序返回。

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.$sort操作不是“稳定排序”,这意味着具有等效排序键的文档不能保证在输出中保持与输入中相同的相对顺序。

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.如果需要一致的排序顺序,请在排序中至少包含一个包含唯一值的字段。保证这一点的最简单方法是在排序查询中包含_id字段。

Consider the following restaurant collection:考虑以下restaurant集合:

db.restaurants.insertMany( [
{ _id: 1, name: "Central Park Cafe", borough: "Manhattan"},
{ _id: 2, name: "Rock A Feller Bar and Grill", borough: "Queens"},
{ _id: 3, name: "Empire State Pub", borough: "Brooklyn"},
{ _id: 4, name: "Stan's Pizzaria", borough: "Manhattan"},
{ _id: 5, name: "Jane's Deli", borough: "Brooklyn"},
] )

The following command uses the $sort stage to sort on the borough field:以下命令使用$sort阶段对borough字段进行排序:

db.restaurants.aggregate(
[
{ $sort : { borough : 1 } }
]
)

In this example, sort order may be inconsistent, since the borough field contains duplicate values for both Manhattan and Brooklyn. 在这个例子中,排序顺序可能不一致,因为borough(行政区)字段包含Manhattan(曼哈顿)和Brooklyn(布鲁克林)的重复值。Documents are returned in alphabetical order by borough, but the order of those documents with duplicate values for borough might not the be the same across multiple executions of the same sort. For example, here are the results from two different executions of the above command:文档按borough按字母顺序返回,但borough值重复的文档的顺序在同一排序的多个执行中可能不同。例如,以下是上述命令的两次不同执行的结果:

{ _id: 3, name: "Empire State Pub", borough: "Brooklyn" }
{ _id: 5, name: "Jane's Deli", borough: "Brooklyn" }
{ _id: 1, name: "Central Park Cafe", borough: "Manhattan" }
{ _id: 4, name: "Stan's Pizzaria", borough: "Manhattan" }
{ _id: 2, name: "Rock A Feller Bar and Grill", borough: "Queens" }

{ _id: 5, name: "Jane's Deli", borough: "Brooklyn" }
{ _id: 3, name: "Empire State Pub", borough: "Brooklyn" }
{ _id: 4, name: "Stan's Pizzaria", borough: "Manhattan" }
{ _id: 1, name: "Central Park Cafe", borough: "Manhattan" }
{ _id: 2, name: "Rock A Feller Bar and Grill", borough: "Queens" }

While the values for borough are still sorted in alphabetical order, the order of the documents containing duplicate values for borough (i.e. Manhattan and Brooklyn) is not the same.虽然borough的值仍然按字母顺序排序,但包含borough重复值的文档(即ManhattanBrooklyn)的顺序并不相同。

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 borough field and the _id field:为了实现一致的排序,请在排序中添加一个仅包含唯一值的字段。以下命令使用$sort阶段对borough字段和_id字段进行排序:

db.restaurants.aggregate(
[
{ $sort : { borough : 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.由于_id字段总是保证只包含唯一值,因此返回的排序顺序在同一排序的多个执行中总是相同的。

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:当MongoDB按数组值字段对文档进行排序时,排序键取决于排序是升序还是降序:

  • 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, create a shoes collection with these documents:例如,使用以下文档创建shoes集合:

db.shoes.insertMany( [
{ _id: 'A', sizes: [ 7, 11 ] },
{ _id: 'B', sizes: [ 8, 9, 10 ] }
] )

The following queries sort the documents by the sizes field in ascending and descending order:以下查询按sizes字段按升序和降序对文档进行排序:

// Ascending sort
db.shoes.aggregate( [
{
$sort: { sizes: 1 }
}
] )

// Descending sort
db.shoes.aggregate( [
{
$sort: { sizes: -1 }
}
] )

Both of the preceding queries return the document with _id: 'A' first because sizes 7 and 11 are the lowest and highest in the entries in the sizes array, respectively.前面的两个查询都首先返回_id: 'A'的文档,因为大小711分别是sizes数组中条目的最低和最高值。

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 shoes with sizes greater than 9 and sorts the results by size in ascending order:例如,以下查询查找尺寸大于9的鞋子,并按尺寸升序对结果进行排序:

db.shoes.aggregate( [
{
$match: { sizes: { $gt: 9 } }
},
{
$sort: { sizes: 1 }
}
] )

The sort is ascending, which means that the sort key is the lowest value in the sizes array:排序是升序的,这意味着排序键是sizes数组中的最低值:

  • In document _id: 'A', the lowest sizes element is 7. This value is used as the sort key even though it does not match the filter { sizes: { $gt: 9 }.在文档_id: 'A'中,最小的sizes元素是7。即使此值与筛选器{ sizes: { $gt: 9 }不匹配,它也会用作排序键。
  • In document _id: 'B', the lowest sizes element is 8. Similarly, this value is used as the sort key even though it does not match the filter.在文档_id: 'B'中,最小sizes元素是8。同样,即使该值与筛选器不匹配,也会将其用作排序键。

The query returns the document with _id: 'A' first.查询首先返回_id: 'A'的文档。

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. $sort位于$limit之前,并且没有修改文档数量的中间阶段时,优化器可以将$limit合并到$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. 这允许$sort操作在执行过程中只维护前n个结果,其中n是指定的限制,并确保MongoDB只需要在内存中存储n个项目。This optimization still applies when allowDiskUse is true and the n items exceed the aggregation memory limit.allowDiskUse为真并且n个项目超过聚合内存限制时,此优化仍然适用。

Optimizations are subject to change between releases.优化可能会在不同版本之间发生变化。

$sort and Memory Restrictions和内存限制

Starting in MongoDB 6.0, 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. 从MongoDB 6.0开始,默认情况下,需要超过100兆字节内存来执行将临时文件写入磁盘的流水线阶段。这些临时文件在管道执行期间持续存在,并可能影响实例上的存储空间。In earlier versions of MongoDB, you must pass { allowDiskUse: true } to individual find and aggregate commands to enable this behavior.在早期版本的MongoDB中,您必须将{ allowDiskUse: true }传递给单个findaggregate命令以启用此行为。

Individual find and aggregate commands can override the allowDiskUseByDefault parameter by either:单个findaggregate命令可以通过以下任一方式覆盖allowDiskUseByDefault参数:

  • Using { allowDiskUse: true } to allow writing temporary files out to disk when allowDiskUseByDefault is set to falseallowDiskUseByDefault设置为false时,使用{ allowDiskUse: true }允许将临时文件写入磁盘
  • Using { allowDiskUse: false } to prohibit writing temporary files out to disk when allowDiskUseByDefault is set to trueallowDiskUseByDefault设置为true时,使用{ allowDiskUse: false }禁止将临时文件写入磁盘

Note

For MongoDB Atlas, it is recommended to configure storage auto-scaling to prevent long-running queries from filling up storage with temporary files.对于MongoDB Atlas,建议配置存储自动扩展,以防止长时间运行的查询用临时文件填满存储。

If your Atlas cluster uses storage auto-scaling, the temporary files may cause your cluster to scale to the next storage tier.如果Atlas集群使用存储自动扩展,临时文件可能会导致集群扩展到下一个存储层。

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 preceeded by a $match stage.如果在管道的第一阶段使用索引,或者只有在$match阶段之前使用索引,则$sort运算符可以利用索引。

When you use the $sort on a sharded cluster, each shard sorts its result documents using an index where available. 当您在分片集群上使用$sort时,每个分片都会使用可用的索引对其结果文档进行排序。Then the mongos or one of the shards performs a streamed merge sort.然后,mongos或其中一个分片执行流式合并排序。

Examples示例

MongoDB Shell

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:对于要排序的字段,将排序顺序设置为1-1,分别指定升序或降序,如下例所示:

db.users.aggregate(
[
{ $sort : { age : -1, posts: 1 } }
]
)

This operation sorts the documents in the users collection, in descending order according by the age field and then in ascending order according to the value in the posts field.此操作对users集合中的文档进行排序,根据age字段按降序排列,然后根据posts字段中的值按升序排列。

When comparing values of different BSON types in sort operations, MongoDB uses the following comparison order, from lowest to highest:在排序操作中比较不同BSON类型的值时,MongoDB使用以下从低到高的比较顺序:

  1. MinKey (internal type)
  2. Null
  3. Numbers (ints, longs, doubles, decimals)
  4. Symbol, String
  5. Object
  6. Array
  7. BinData
  8. ObjectId
  9. Boolean
  10. Date
  11. Timestamp
  12. Regular Expression
  13. JavaScript Code
  14. JavaScript Code with Scope
  15. 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.$text为自我管理(非Atlas)部署提供文本查询功能。对于托管在MongoDB上的数据,MongoDB还提供了改进的全文查询解决方案MongoDB搜索

For a pipeline that includes $text, you can sort by descending relevance score using the { $meta: "textScore" } expression. 对于包含$text的管道,您可以使用{ $meta: "textScore" }表达式按相关性得分降序排序。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:{ <sort-key> }文档中,将{ $meta: "textScore" }表达式设置为任意字段名。字段名被查询系统忽略。例如:

db.users.aggregate(
[
{ $match: { $text: { $search: "operating" } } },
{ $sort: { score: { $meta: "textScore" }, posts: -1 } }
]
)

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 posts field in descending order. 此操作使用$text运算符匹配文档,然后首先按"textScore"元数据降序排序,然后按posts字段降序排序。The score field name in the sort document is ignored by the query system. In this pipeline, the "textScore" metadata is not included in the projection and is not returned as part of the matching documents. 查询系统会忽略排序文档中的score字段名称。在此管道中,"textScore"元数据不包含在投影中,也不会作为匹配文档的一部分返回。See $meta for more information.有关更多信息,请参阅$meta

C#

The C# examples on this page use the sample_mflix database from the Atlas sample datasets. 本页上的C#示例使用Atlas示例数据集中的sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB .NET/C# Driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB .NET/C#驱动程序文档中的入门

The following Movie class models the documents in the sample_mflix.movies collection:以下Movie类对sample_mflix.movies集合中的文档进行建模:

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; }

[BsonElement("lastupdated")]
public DateTime LastUpdated { get; set; }
}

Note

ConventionPack for Pascal CasePascal大小写的约定包

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:此页面上的C#类使用Pascal大小写作为其属性名,但MongoDB集合中的字段名使用驼峰大小写。为了解释这种差异,您可以在应用程序启动时使用以下代码注册ConventionPack

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.要使用MongoDB .NET/C#驱动程序向聚合管道添加$sort阶段,请在PipelineDefinition对象上调用Sort()方法。

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:以下示例创建了一个管道阶段,该阶段首先按Year字段降序排列输入的Movie文档,然后按Title字段升序排列:

var pipeline = new EmptyPipelineDefinition<Movie>()
.Sort(Builders<Movie>.Sort.Combine(
Builders<Movie>.Sort.Descending(m => m.Year),
Builders<Movie>.Sort.Ascending(m => m.Title)));
Node.js

The Node.js examples on this page use the sample_mflix database from the Atlas sample datasets. 本页上的Node.js示例使用Atlas示例数据集中的sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB Node.js driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB Node.js驱动程序文档中的入门

To use the MongoDB Node.js driver to add a $sort stage to an aggregation pipeline, use the $sort operator in a pipeline object.要使用MongoDB Node.js驱动程序向聚合管道添加$sort阶段,请在管道对象中使用$sort运算符。

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:以下示例创建了一个管道阶段,该阶段首先按year字段降序排列输入的movie文档,然后按title字段升序排列。然后,该示例运行聚合管道:

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.要查看使用$sort阶段的完整聚合示例,请参阅完整的聚合管道教程