Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

$sort(聚合)

在此页面上

  • 定义
  • 兼容性
  • 语法
  • 行为
  • 举例
  • $sort 操作符和内存
  • $sort 操作符和性能
$sort

将所有输入文档进行排序,然后按照排序将其返回至管道。

可以使用 $sort 查找托管在以下环境中的部署:

  • MongoDB Atlas :用于在云中部署 MongoDB 的完全托管服务

  • MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本

  • MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本

$sort 阶段具有以下原型形式:

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }

$sort 接受指定要作为排序依据的字段以及相应排序顺序的文档。<sort order> 可能具有以下任意一个值:

说明
1
升序排序。
-1
降序排序。
{ $meta: "textScore" }
按计算的 textScore 元数据降序排序
顺序。请参阅文本分数元数据排序,查看示例。

如果对多个字段进行排序,则按从左到右的顺序进行排序。例如,在上面的表单中,文档首先按 <field1> 排序。然后,具有相同 <field1> 值的文档将按 <field2> 进一步排序。

您最多可以对 32 个键进行排序。

MongoDB 不按特定顺序将文档存储在集合中。对包含重复值的字段进行排序时,可能会以任何顺序返回包含这些值的文档。

如果需要一致的排序顺序,请在排序中至少纳入一个包含唯一值的字段。最简单方法是在排序查询中纳入 _id 字段。

考虑以下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"},
] )

以下命令使用 $sort 阶段对 borough 字段进行排序:

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

在此示例中,排序顺序可能不一致,因为 borough 字段包含 ManhattanBrooklyn 的重复值。文档按 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" }

虽然 borough 的值仍按字母顺序排序,但包含 borough 重复值的文档(即 ManhattanBrooklyn)的顺序不同。

要实现一致的排序,请在排序中添加一个仅包含唯一值的字段。以下命令使用 $sort 阶段对 borough 字段和 _id 字段进行排序:

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

由于 _id 字段始终保证包含唯一值,因此在同一排序的多次执行中返回的排序顺序将始终相同。

当 MongoDB 按数组值字段对文档进行排序时,排序键取决于排序是升序还是降序:

  • 在升序排序中,排序键是数组中的最低值。

  • 在降序排序中,排序键是数组中的最高值。

查询筛选器不影响排序键选择。

例如,使用以下文档创建shoes集合:

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

以下查询按sizes字段的升序和降序对文档进行排序:

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

前面的两个查询首先返回包含_id: 'A'的文档,因为大小711分别是sizes数组中条目的最小和最大。

对于要作为排序依据的一个或多个字段,请将排序顺序设置为 1-1 以分别指定升序或降序,如下例所示:

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

此操作对 users 集合中的文档进行排序,先根据 age 字段降序排列,再根据 posts 字段中的值升序排序。

在排序操作中比较不同 BSON 类型的值时,MongoDB 使用以下从低到高的比较顺序:

  1. MinKey(内部类型)

  2. null

  3. 数值(int、long、double、decimal)

  4. 符号,字符串

  5. 对象

  6. 阵列

  7. BinData

  8. ObjectId

  9. 布尔

  10. Date

  11. 时间戳

  12. 正则表达式

  13. MaxKey(内部类型)

有关特定类型的比较/排序顺序的详细信息,请参阅比较/排序顺序。

注意

$text 为自管理(非 Atlas)部署提供文本查询功能。对于 MongoDB Atlas 上托管的数据,MongoDB 提供了改进的全文查询解决方案Atlas Search。

对于包含$text的管道,您可以使用{ $meta: "textScore" }表达式按相关性分数降序排序。在{ <sort-key> }文档中,将{ $meta: "textScore" }表达式设置为任意字段名称。查询系统会忽略字段名称。例如:

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

此操作使用$text操作符匹配文档,然后首先按"textScore"元数据降序排序,然后按posts字段降序排序。查询系统会忽略排序文档中的score字段名称。在此管道中, "textScore"元数据不包含在投影中,也不作为匹配文档的一部分返回。有关更多信息,请参阅$meta

$sort$limit 之前,并且不存在修改文档数量的干预阶段,那么优化器可以将 $limit 合并到 $sort 中。这可以让 $sort 操作在进行过程中仅保留前 n 项结果(其中 n 是指定的限制值),并确保 MongoDB 只需在内存中存储 n 个项目。当 allowDiskUsetruen 个项目超过了聚合内存限制时,此优化仍然适用。

优化可能因版本而异。

从 MongoDB 6开始。 0 ,需要超过100 MB 内存才能执行的管道阶段,默认会将临时文件写入磁盘。这些临时文件在管道执行期间持续存在,可能会影响实例上的存储空间。在 MongoDB 的早期版本中,您必须将{ allowDiskUse: true }传递给各个findaggregate命令才能启用此行为。

单个findaggregate命令可以通过以下任一方式覆盖allowDiskUseByDefault参数:

  • 使用 { allowDiskUse: true } 以允许在 allowDiskUseByDefault 设置为 false 时将临时文件写入磁盘

  • 使用 { allowDiskUse: false } 以禁止在 allowDiskUseByDefault 设置为 true 时将临时文件写入磁盘

注意

对于 MongoDB Atlas,建议配置存储自动伸缩,以防止长时间运行的查询用临时文件填满存储。

如果您的 Atlas 集群使用存储自动伸缩,则临时文件可能会导致集群扩展到下一个存储层。

有关更多详细信息,请参阅聚合管道限制。

$sort 操作符如果用在管道的第一阶段或者其前面仅有 $match 阶段,则该操作符可以利用索引。

当您在分片集群上使用 $sort 时,每个分片都会使用可用索引对其结果文档排序。然后 mongos 或一个分片会执行流式合并排序。

提示

另请参阅:

后退

$skip