当前位置:   article > 正文

MongoDB聚合运算符:$zip

MongoDB聚合运算符:$zip

MongoDB聚合运算符:$zip


$zip用于将输入数组的元素重新组合转换为新的数组,重组转换的的规则是使用输入数组的第一个元素重组为第一个数组,使用第二个元素重组为第二个数组,以此类推。

例如,[ [ 1, 2, 3 ], [ "a", "b", "c" ] ]转换后为[ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ] ]

语法

{
    $zip: {
        inputs: [ <array expression1>,  ... ],
        useLongestLength: <boolean>,
        defaults:  <array expression>
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • inputs:表达式数组,数组的每个表达式可解析为数组。这些输入数组的元素组合成输出数组。
    如果任何一个输入数组的解析值为空或指向一个缺失字段,$zip将返回空值。
    如果输入数组中的任何一个没有解析为数组或空值,或者指向一个缺失字段,$zip将返回错误信息。
  • useLongestLength:布尔值,用于指定最长数组的长度是否决定输出数组中数组的个数。
    默认值为 false,最短数组的长度决定输出数组中数组的个数。
  • 如果输入数组的长度不同,则使用默认元素值数组。必须同时指定 useLongestLength: true,否则$zip将返回错误。
    如果useLongestLength: true,但defaults为空或未指定,$zip将使用null作为默认值。
    如果指定了非空defaults,则必须为每个输入数组指定默认值,否则$zip返回错误。

使用

输入数组的长度不要求相同。默认情况下,输出数组的长度为最短输入数组的长度,但useLongestLength选项可以指定$zip输出与最长输入数组的长度是否一致。

参考下面的例子来说明:

例1:

{ $zip: { inputs: [ [ "a" ], [ "b" ], [ "c" ] ] }}
  • 1

结果:

[ [ "a", "b", "c" ] ]
  • 1

例2:

{ $zip: { inputs: [ [ "a" ], [ "b", "c" ] ] } }
  • 1

结果:

[ [ "a", "b" ] ]
  • 1

例3:

{
  $zip: {
     inputs: [ [ 1 ], [ 2, 3 ] ],
     useLongestLength: true
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果:

[ [ 1, 2 ], [ null, 3 ] ]
  • 1

例4:

{
  $zip: {
     inputs: [ [ 1 ], [ 2, 3 ], [ 4 ] ],
     useLongestLength: true,
     defaults: [ "a", "b", "c" ]
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果:

因为useLongestLength: true$zip会用缺省值元素填充较短的输入数组。

[ [ 1, 2, 4 ], [ "a", 3, "c" ] ]
  • 1

举例

矩阵转置

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

db.matrices.insertMany([
  { matrix: [[1, 2], [2, 3], [3, 4]] },
  { matrix: [[8, 7], [7, 6], [5, 4]] },
])
  • 1
  • 2
  • 3
  • 4

要计算这个集合中每个 3x2 矩阵的转置,可以使用下面的聚合运算:。

db.matrices.aggregate([{
  $project: {
    _id: false,
    transposed: {
      $zip: {
        inputs: [
          { $arrayElemAt: [ "$matrix", 0 ] },
          { $arrayElemAt: [ "$matrix", 1 ] },
          { $arrayElemAt: [ "$matrix", 2 ] },
        ]
      }
    }
  }
}])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

执行的结果为:

{ "transposed" : [ [ 1, 2, 3 ], [ 2, 3, 4 ] ] }
{ "transposed" : [ [ 8, 7, 5 ], [ 7, 6, 4 ] ] }
  • 1
  • 2

过滤并保留索引

可以使用$zip$filter来获取数组中的元素子集,同时保存每个元素的原始索引。

使用脚本创建pages集合:

db.pages.insertOne( {
  "category": "unix",
  "pages": [
    { "title": "awk for beginners", reviews: 5 },
    { "title": "sed for newbies", reviews: 0 },
    { "title": "grep made simple", reviews: 2 },
] } )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

下面的聚合首先把pages数组中的元素连同其索引一起压缩,然后只筛选出至少有一条评论的页面::

db.pages.aggregate([{
  $project: {
    _id: false,
    pages: {
      $filter: {
        input: {
          $zip: {
            inputs: [ "$pages", { $range: [0, { $size: "$pages" }] } ]
          }
        },
        as: "pageWithIndex",
        cond: {
          $let: {
            vars: {
              page: { $arrayElemAt: [ "$$pageWithIndex", 0 ] }
            },
            in: { $gte: [ "$$page.reviews", 1 ] }
          }
        }
      }
    }
  }
}])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

结果为:

{
  "pages" : [
    [ { "title" : "awk for beginners", "reviews" : 5 }, 0 ],
    [ { "title" : "grep made simple", "reviews" : 2 }, 2 ] ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/580209
推荐阅读
  

闽ICP备14008679号