压缩(聚合)
定义
$zip
将输入数组的数组进行转置,以便输出数组的第一个元素是一个包含第一个输入数组的第一个元素、第二个输入数组的第一个元素等组成的数组。
例如,
$zip
将[ [ 1, 2, 3 ], [ "a", "b", "c" ] ]
转换为[ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ] ]
。$zip
的语法如下{ $zip: { inputs: [ <array expression1>, ... ], useLongestLength: <boolean>, defaults: <array expression> } } 操作数描述inputs
一个布尔值,指定是否由最长数组的长度确定输出数组中的数组数量。
默认值是
false
:最短数组长度确定输出数组中的数组数量。defaults
一个数组,包含用于输入数组不同长度的默认元素值。您必须指定
useLongestLength: true
以及此字段,否则$zip
将返回错误。
行为
输入数组不需要具有相同的长度。默认情况下,输出数组的长度与最短的输入数组相同,但 useLongestLength
选项指示 $zip
输出与最长的输入数组一样长的数组。
示例 | 结果 | |||||||
---|---|---|---|---|---|---|---|---|
|
| |||||||
|
| |||||||
|
| |||||||
| 由于 这会产生 |
示例
矩阵转置
名为 matrices
的集合包含以下文档
db.matrices.insertMany([ { matrix: [[1, 2], [2, 3], [3, 4]] }, { matrix: [[8, 7], [7, 6], [5, 4]] }, ])
要计算此集合中每个 3x2 矩阵的转置,可以使用以下聚合操作
db.matrices.aggregate([{ $project: { _id: false, transposed: { $zip: { inputs: [ { $arrayElemAt: [ "$matrix", 0 ] }, { $arrayElemAt: [ "$matrix", 1 ] }, { $arrayElemAt: [ "$matrix", 2 ] }, ] } } } }])
这将返回以下 2x3 矩阵
{ "transposed" : [ [ 1, 2, 3 ], [ 2, 3, 4 ] ] } { "transposed" : [ [ 8, 7, 5 ], [ 7, 6, 4 ] ] }
过滤和保留索引
您可以使用$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 }, ] } )
以下聚合管道将首先将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 ] } } } } } } }])
这将返回以下文档
{ "pages" : [ [ { "title" : "awk for beginners", "reviews" : 5 }, 0 ], [ { "title" : "grep made simple", "reviews" : 2 }, 2 ] ] }