Definition 定义
对所有输入的文档进行排序,并按排序后的顺序返回给 pipeline。
$sort stage 的原型形式如下:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
$sort 接收一个文档,指定要排序的字段和各自的排序顺序。<sort order>可以有以下值之一:
| Value | Description |
|---|---|
1 |
升序排序(ascending) |
-1 |
降序排序(descending) |
{ $meta: "textScore" } |
按计算的 textScore 元数据降序排序。 有关示例,请参阅 Text Score Metadata Sort(文本分数元数据排序)。 |
如果对多个字段进行排序,排序顺序将从左到右进行评估。例如,在上面的原型中,文档首先按 <field1> 进行排序。然后,具有相同 <field1> 值的文档进一步按 <field2> 进行排序。
Behavior 行为
Sort Consistency 一致性排序
MongoDB 不会以特定顺序将文档存储在集合中。 在对包含重复值的字段进行排序时,包含这些值的文档可以按任何顺序返回。
如果需要一致的排序顺序,请在排序中至少包含一个包含唯一值的字段。 保证这一点的最简单方法是在排序查询中包含 _id 字段。
考虑以下 restaurants collection:
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 stage 对 borough 字段进行排序(升序):
db.restaurants.aggregate( [{$sort: { borough: 1 }}] )
在此示例中,排序顺序可能不一致,因为 borough 字段包含 Manhattan 和 Brooklyn 的重复值。 文档是按 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 的值仍按字母顺序(alphabetical order)排序,但包含 borough 重复值(即 Manhattan 和 Brooklyn)的文档的顺序并不相同。
要实现一致的排序,请向排序添加一个仅包含唯一值的字段。 以下命令使用 $sort stage 对 borough 字段和 _id 字段进行排序:
db.restaurants.aggregate( [{$sort: { borough: 1, _id: 1 }}] )
由于 _id 字段始终保证包含唯一的值,因此返回的排序顺序在同一排序的多次执行中总是相同的。
Example 例子
Asceding/Descending Sort 升序/降序排序
对于要排序的一个或多个字段,将排序顺序设置为 1 或 -1 以分别指定升序或降序排序,如下例所示:
db.users.aggregate([{ $sort : { age : -1, posts: 1 } }])
该 operation 对 users collection 中的文档进行排序,按照 age 字段降序排列,然后按照 posts 字段中的值升序排列。
在比较不同 BSON 类型的值时,MongoDB 使用以下比较顺序,从低到高:
- MinKey(internal type)
- Null
- Numbers(ints、longs、doubles、decimals)
- Symbol,String
- Object
- Array
- BinData
- ObjectId
- Boolean
- Date
- Timestamp
- Regular Expression
- MaxKey(interval type)
有关特定类型的比较/排序顺序的详细信息,请参阅 Comparison/Sort Order。
Text Score Metadata Sort 文本分数元数据排序
对于包含 $text 搜索的 pipeline,您可以使用 { $meta: “textScore” } expression 按相关性分数降序排序。 在 { <sort-key> } 文档中,将 { $meta: “textScore” } expression 设置为任意字段名称。 查询系统会忽略字段名称。 例如:
db.users.aggregate([{ $match: { $text: { $search: "operating" } } },{ $sort: { score: { $meta: "textScore" }, posts: -1 } }])
此操作使用 $text operator 匹配文档,然后首先按 "textScore" metadata 降序排序,然后按 posts 字段降序排序。 排序文档中的 score 字段名称被查询系统忽略。 在此 pipeline 中,"textScore" metadata 不包含在 projection 中,也不作为匹配文档的一部分返回。 有关更多信息,请参阅 $meta。
$sort Operator and Memory $sort 运算符和内存
$sort + $limit Memory Optimization $sort + $limit 内存优化
当 $sort 在 $limit 之前并且没有修改文档数量的干预 stage 时,优化器可以将 $limit 合并到 $sort 中。 这允许 $sort operation 在进行时只维护前 n 个结果,其中 n 是指定的限制,并确保 MongoDB 只需要在内存中存储 n 个项目(items)。 当 allowDiskUse 为 true 并且 n 项(items)超过 aggregation memory limit(聚合内存限制)时,此优化仍然适用。
$sort and Memory Restrictions $sort 和内存限制
$sort stage 对内存中的排序有 100 兆字节的 RAM 限制。 默认情况下,如果 stage 超过此限制, $sort 会产生错误。 要允许 pipeline 处理占用更多空间,请使用 allowDiskUse 选项启用 aggregation pipeline stage 以将数据写入临时文件。
TIP 参阅: Aggregation Pipeline Limits 聚合管道限制
$sort Operator and Performance $sort 运算符和性能
如果 $sort operator 用于 pipeline 的第一 stage 或仅在 $match stage之前使用,则它可以利用索引(index)。
当您在分片集群(sharded cluster)上使用 $sort 时,每个分片都会使用可用的索引对其结果文档进行排序。 然后 mongos 或其中一个分片执行流式合并排序。
TIP 参阅:
- Aggregation with the Zip Code Data Set 用邮编数据集进行 aggregation
- Aggregation with User Preference Data 用用户偏好数据进行 aggregation
参考
https://docs.mongodb.com/manual/reference/operator/aggregation/sort
