MongoDB聚合运算符:$sortArray

MongoDB聚合运算符:$sortArray


$sortArray聚合运算符根据指定的排序规则对数组元素进行排序。

语法

$sortArray: {
   input: <array>,
   sortBy: <sort spec>
}
  • input:为可解析为数组的表达式,如果表达式字段缺失、为null或undefined,则返回null,如果表达式为其他非数组的值,则返回错误。
  • sortBy:文档类型,用于指定排序方式。

使用

  • $sortArray 表达式根据 sortBy 规范对输入数组进行排序。
  • $sortArray 的语法和语义与通过 $sort 修改的 $push 操作中的行为相同。

根据文档字段进行排序

如果数组元素是文档,则可以按文档字段排序,指定字段名称和排序方向:升序 (1) 或降序 (-1)。

{
   input: <array-of-documents>,
   sortBy: { <document-field>: <sort-direction> }
}

根据值排序

要按值对整个数组进行排序,或按非文档的数组元素进行排序,需要指定输入数组并在 sortBy 参数中指定 1 表示升序排序,或指定 -1 表示降序排序。

{
   input: <array-of-documents>,
   sortBy: <sort-direction>
}

注意事项

  • 对于排序的键值,不会进行隐式数组遍历。
  • 不支持位置运算符,像"values.1"这样的字段名称表示 value 数组中名为"1"的子字段,而不是引用数组中的第1个元素。
  • 当整个数组排序时,排序按字典顺序,与聚合 $sort 阶段的行为有所不同。
  • 当数组按字段排序时,任何不具有指定字段的文档或标量会被平均排序,也就是结果的排序顺序不确定。
  • null和缺失值按照同等顺序排序。
  • $sortArray的排序是不稳定的,不应依赖其排序算法的稳定性。

举例

使用下面的脚本创建team集合:

db.engineers.insertOne(
   {
      "team":
         [
            {
              "name": "pat",
              "age": 30,
              "address": { "street": "12 Baker St", "city": "London" }
            },
            {
              "name": "dallas",
              "age": 36,
              "address": { "street": "12 Cowper St", "city": "Palo Alto" }
            },
            {
              "name": "charlie",
              "age": 42,
              "address": { "street": "12 French St", "city": "New Brunswick" }
            }
         ]
   }
)

team 数组包含三个元素,其每个元素都有嵌套的子元素:姓名name、年龄age和地址address。下面的例子演示如何使用这些子元素对 team 数组进行排序。

根据字段排序

根据指定的字段对数组元素进行排序:

db.engineers.aggregate( [
   { $project:
      {
          _id: 0,
          result:
            {
               $sortArray: { input: "$team", sortBy: { name: 1 } }
            }
      }
   }
] )

name字段是team数组的子元素,操作返回以下结果::

{
   result:
   [
      {
        name: 'charlie',
        age: 42,
        address: { street: '12 French St', city: 'New Brunswick' }
      },
      {
        name: 'dallas',
        age: 36,
        address: { street: '12 Cowper St', city: 'Palo Alto' }
      },
      {
        name: 'pat',
        age: 30,
        address: { street: '12 Baker St', city: 'London' }
      }
   ]
}

根据子字段排序

address字段是文档的子字段,使用点号.根据子字段对数组进行排序:

db.engineers.aggregate( [
   {
      $project:
         {
                _id: 0,
                result:
               {
                  $sortArray:
                     {
                        input: "$team",
                        sortBy: { "address.city": -1 }
                     }
               }
             }
   }
] )

由于 sortBy 值为-1,因此排序方向为降序,结果如下:

{
  result: [
    {
      name: 'dallas',
      age: 36,
      address: { street: '12 Cowper St', city: 'Palo Alto' }
    },
    {
      name: 'charlie',
      age: 42,
      address: { street: '12 French St', city: 'New Brunswick' }
    },
    {
      name: 'pat',
      age: 30,
      address: { street: '12 Baker St', city: 'London' }
    }
  ]
}

根据多个字段排序

指定多个索引字段进行复合排序:

db.engineers.aggregate( [
   {
      $project:
         {
            _id: 0,
            result:
               {
                  $sortArray:
                     {
                        input: "$team",
                        sortBy: { age: -1, name: 1 }
                     }
               }
         }
    }
 ] )

操作返回以下结果::

{
  name: 'charlie',
  age: 42,
  address: { street: '12 French St', city: 'New Brunswick' }
},
{
  name: 'dallas',
  age: 36,
  address: { street: '12 Cowper St', city: 'Palo Alto' }
},
{
  name: 'pat',
  age: 30,
  address: { street: '12 Baker St', city: 'London' }
}

对整数数组排序

本例直接指定了一个输入数组,所有值的类型都是Int32

db.engineers.aggregate( [
   {
      $project:
         {
            _id: 0,
            result:
               {
                  $sortArray:
                     {
                         input: [ 1, 4, 1, 6, 12, 5 ],
                         sortBy: 1
                     }
               }
         }
   }
] )

输入数组的第 0 位和第 2 位都有一个 "1"。在结果中,"1"会被分组,但并不保证 "1"组的排序与原始顺序一致。

操作返回以下结果::

[ { result: [ 1, 1, 4, 5, 6, 12 ] } ]

对混合类型字段进行排序

本例直接指定一个输入数组,这些值有不同的类型:

db.engineers.aggregate( [
   {
      $project:
         {
            _id: 0,
            result:
            {
               $sortArray:
                  {
                     input: [ 20, 4, { a: "Free" }, 6, 21, 5, "Gratis",
                             { a: null }, { a: { sale: true, price: 19 } },
                             Decimal128( "10.23" ), { a: "On sale" } ],
                     sortBy: 1
                  }
            }
         }
   }
] )

name字段是team数组的子元素,操作返回以下结果::

{ result: [
      4,
      5,
      6,
      Decimal128("10.23"),
      20,
      21,
      'Gratis',
      { a: null },
      { a: 'Free' },
      { a: 'On sale' },
      { a: { sale: true, price: 19 } }
] }

结果是有序的。相反,将 sortBy 字段改为根据文档字段之一(sortBy: { a: 1 } 排序后,标量值和空值的排序顺序未定义:

{ result: [
     20,
     4,
     6,
     21,
     5,
     'Gratis',
     { a: null },
     Decimal128("10.23"),
     { a: 'Free' },
     { a: 'On sale' },
     { a: { sale: true, price: 19 } }
] }
  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原子星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值