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