$zip (aggregation)

On this page本页内容

Definition定义

$zip

New in version 3.4.版本3.4中的新功能。

Transposes an array of input arrays so that the first element of the output array would be an array containing, the first element of the first input array, the first element of the second input array, etc.转换输入数组的数组,使输出数组的第一个元素是一个包含第一个输入数组的第一个元素、第二个输入数组的第一个元素等的数组。

For example, $zip would transform [ [ 1, 2, 3 ], [ "a", "b", "c" ] ] into [ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ] ].例如,$zip会将[ [ 1, 2, 3 ], [ "a", "b", "c" ] ]转换为[ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ] ]

$zip has the following syntax:语法如下所示:

{
    $zip: {
        inputs: [ <array expression1>,  ... ],
        useLongestLength: <boolean>,
        defaults:  <array expression>
    }
}
Operand操作数Description描述
inputs

An array of expressions that resolve to arrays. 解析为数组的表达式数组。The elements of these input arrays combine to form the arrays of the output array.这些输入数组的元素组合成输出数组的数组。

If any of the inputs arrays resolves to a value of null or refers to a missing field, $zip returns null.如果任何inputs数组解析为null值或引用缺少的字段,则$zip返回null

If any of the inputs arrays does not resolve to an array or null nor refers to a missing field, $zip returns an error.如果任何inputs数组未解析为数组或null,也未引用缺少的字段,$zip将返回一个错误。

useLongestLength

A boolean which specifies whether the length of the longest array determines the number of arrays in the output array.一个布尔值,指定最长数组的长度是否决定输出数组中的数组数。

The default value is false: the shortest array length determines the number of arrays in the output array.默认值为false:最短数组长度决定了输出数组中的数组数。

defaults

An array of default element values to use if the input arrays have different lengths. 如果输入数组具有不同的长度,则要使用的默认元素值数组。You must specify useLongestLength: true along with this field, or else $zip will return an error.必须在该字段中指定useLongestLength:true,否则$zip将返回错误。

If useLongestLength: true but defaults is empty or not specified, $zip uses null as the default value.如果useLongestLength:truedefaults为空或未指定,$zip将使用null作为默认值。

If specifying a non-empty defaults, you must specify a default for each input array or else $zip will return an error.如果指定非空defaults,则必须为每个输入数组指定默认值,否则$zip将返回错误。

Behavior行为

The input arrays do not need to be of the same length. 输入数组不需要具有相同的长度。By default, the output array has the length of the shortest input array, but the useLongestLength option instructs $zip to output an array as long as the longest input array.默认情况下,输出数组的长度与最短输入数组的长度相同,但useLongestLength选项指示$zip输出与最长输入数组长度相同的数组。

Example示例Results结果
{ $zip: { inputs: [ [ "a" ], [ "b" ], [ "c" ] ] }
[ [ "a", "b", "c" ] ]
{ $zip: { inputs: [ [ "a" ], [ "b", "c" ] ] } }
[ [ "a", "b" ] ]
{
  $zip: {
     inputs: [ [ 1 ], [ 2, 3 ] ],
     useLongestLength: true
  }
}
[ [ 1, 2 ], [ null, 3 ] ]
{
  $zip: {
     inputs: [ [ 1 ], [ 2, 3 ], [ 4 ] ],
     useLongestLength: true,
     defaults: [ "a", "b", "c" ]
  }
}

Because useLongestLength: true, $zip will pad the shorter input arrays with the corresponding defaults elements.因为useLongestLength:true$zip将用相应的defaults元素填充较短的输入数组。

This yields [ [ 1, 2, 4 ], [ "a", 3, "c" ] ].

Example示例

Matrix Transposition矩阵变换

A collection called matrices contains the following documents:名为matrices的集合包含以下文档:

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

To compute the transpose of each 3x2 matrix in this collection, you can use the following aggregation operation:要计算此集合中每个3x2矩阵的转置,可以使用以下聚合操作:

db.matrices.aggregate([{
  $project: {
    _id: false,
    transposed: {
      $zip: {
        inputs: [
          { $arrayElemAt: [ "$matrix", 0 ] },
          { $arrayElemAt: [ "$matrix", 1 ] },
          { $arrayElemAt: [ "$matrix", 2 ] },
        ]
      }
    }
  }
}])

This will return the following 2x3 matrices:这将返回以下2x3矩阵:

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

Filtering and Preserving Indexes筛选和保存索引

You can use $zip with $filter to obtain a subset of elements in an array, saving the original index alongside each retained element.您可以使用$zip$filter来获取数组中元素的子集,并将原始索引与每个保留的元素一起保存。

A collection called pages contains the following document:名为pages的集合包含以下文档:

db.pages.save( {
  "category": "unix",
  "pages": [
    { "title": "awk for beginners", reviews: 5 },
    { "title": "sed for newbies", reviews: 0 },
    { "title": "grep made simple", reviews: 2 },
] } )

The following aggregation pipeline will first zip the elements of the pages array together with their index, and then filter out only the pages with at least one review:下面的聚合管道将首先将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 ] }
          }
        }
      }
    }
  }
}])

This will return the following document:这将返回以下文档:

{
  "pages" : [
    [ { "title" : "awk for beginners", "reviews" : 5 }, 0 ],
    [ { "title" : "grep made simple", "reviews" : 2 }, 2 ] ]
}