MongoDB聚合: $sort

聚合的$sort阶段对所有输入文件进行排序,并按排序顺序返回管道。

语法

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

$sort阶段参数为一个文档,该文档指定了要排序的字段和相应的排序顺序。<sort order>为下列值之一:

含义
1 正序(由小到大)
2 逆序(由大到小)
{ $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"},
] )

使用$sortborough字段进行排序:

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的值仍按字母顺序排序,但包含重复区值(即ManhattanBrooklyn)的文档的顺序却不一样。

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

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

由于_id字段是唯一值,因此在多次执行同一排序时,返回的排序顺序总是相同的。

举例

升序/降序排序

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

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

该操作将用户集合中的文档按照age字段降序排序,然后按照posts字段的值升序排序。

在排序操作中比较不同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. MaxKey (internal type)

文本得分元数据排序

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

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

此操作使用$text操作符匹配文档,然后首先按"textScore"元数据降序排序,然后按帖子字段降序排序。查询系统会忽略排序文档中的分数字段名称。在这个流程中,"textScore"元数据不包含在预测中,也不会作为匹配文档的一部分返回。

$sort操作和内存

$sort + $limit 内存优化

$sort$limit之前,且中间没有修改文档数量的阶段时,优化器可以将$limit合并到$sort这样,$sort操作在进行过程中只保留前n个结果(其中n是指定的限制),并确保MongoDB只需在内存中存储n个条目。当allowDiskUsetruen项超过聚合内存限制时,该优化仍然适用。不同版本之间的优化可能会有变化。

$sort和内存限制

$sort受100M内存使用限制,但如果需要,可以将临时文件写入磁盘。从 MongoDB 6.0开始,需要超过100MB内存才能执行的管道阶段默认会将临时文件写入磁盘。在MongoDB早期版本中,要启用此行为,必须传递{ allowDiskUse: true }

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

  • allowDiskUseByDefault设置为false时,使用{ allowDiskUse: true}可以把临时文件写入磁盘

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

$sort和性能

如果$sort用于管道的第一阶段,或仅在$match阶段之前使用,则可以利用索引的优势。

当使用$sort时,每个分片会使用可用的索引对文档进行排序,然后,mongos或其中一个分片执行流式合并排序。

相关推荐

  1. MongoDB聚合: $sort

    2024-02-09 11:34:02       47 阅读
  2. MongoDB聚合运算符:$sqrt

    2024-02-09 11:34:02       34 阅读
  3. MongoDB聚合管道:$match

    2024-02-09 11:34:02       50 阅读
  4. MongoDB聚合:$out

    2024-02-09 11:34:02       59 阅读
  5. MongoDB聚合:$replaceRoot

    2024-02-09 11:34:02       54 阅读
  6. MongoDB聚合:$addField

    2024-02-09 11:34:02       64 阅读
  7. MongoDB聚合:$facet

    2024-02-09 11:34:02       55 阅读
  8. MongoDB聚合:$bucket

    2024-02-09 11:34:02       46 阅读
  9. MongoDB聚合:$bucketAuto

    2024-02-09 11:34:02       49 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-09 11:34:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-09 11:34:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-09 11:34:02       87 阅读
  4. Python语言-面向对象

    2024-02-09 11:34:02       96 阅读

热门阅读

  1. 编程中“游戏心切”心态的影响及其对策探讨

    2024-02-09 11:34:02       48 阅读
  2. GEE python——根据 GPS 轨迹绘制海拔高度剖面图

    2024-02-09 11:34:02       49 阅读
  3. 同步復位和異步復位二者各自的優缺點

    2024-02-09 11:34:02       49 阅读
  4. STM32DMA

    STM32DMA

    2024-02-09 11:34:02      38 阅读
  5. axios-retry 响应异常

    2024-02-09 11:34:02       48 阅读
  6. 梯度提升树系列3——利用GBDT进行回归分析

    2024-02-09 11:34:02       53 阅读
  7. office文件转pdf在线预览

    2024-02-09 11:34:02       38 阅读
  8. LeetCode魔塔游戏

    2024-02-09 11:34:02       49 阅读
  9. SQL面试题挑战15:sql实现分钟级的趋势图

    2024-02-09 11:34:02       55 阅读
  10. Debezium发布历史117

    2024-02-09 11:34:02       49 阅读
  11. Android studio 六大基本布局详解

    2024-02-09 11:34:02       50 阅读