MongoDB 4.2合并多维数组并移除None值(不使用$unwind)
解决MongoDB 4.2多维数组合并为一维并移除Null值(不使用$unwind)
嗨,我完全理解你不想用$unwind的顾虑——在处理大规模数据集时,这个操作确实会带来不小的性能损耗。针对你的需求,我们可以用MongoDB 4.2原生支持的$reduce、$concatArrays和$filter组合来实现,全程不需要依赖$unwind。
先说明下:你提到的None在MongoDB中实际存储的是null值,所以我们的过滤逻辑会针对null来处理。
完整聚合管道代码
db.collection.aggregate([ { $addFields: { // 处理time字段:仅扁平化多维数组 "time": { $reduce: { input: "$time", initialValue: [], in: { $concatArrays: ["$$value", "$$this"] } } }, // 处理bar字段:先过滤子数组中的null,再扁平化 "bar": { $reduce: { input: "$bar", initialValue: [], in: { $concatArrays: [ "$$value", { $filter: { input: "$$this", cond: { $ne: ["$$this", null] } } } ] } } } } } ])
代码逻辑拆解
针对time字段的处理
time字段只需要把多维数组拍平成一维,不需要过滤值:
- 用
$reduce遍历外层数组,初始值设为空数组 - 每次迭代时,用
$concatArrays把当前子数组($$this)和之前累积的结果数组($$value)拼接起来,最终得到完整的一维数组
针对bar字段的处理
bar字段需要先过滤每个子数组里的null,再进行扁平化:
- 同样用
$reduce遍历外层数组,初始值为空数组 - 在每次迭代中,先对当前子数组
$$this用$filter过滤掉null值($ne: ["$$this", null]表示保留所有不等于null的元素) - 再用
$concatArrays把过滤后的子数组和累积的结果数组拼接,最终得到不含null的一维数组
验证结果
针对你提供的输入文档:
{ "time" :[ [ISODate("2018-12-18T20:16:28.800Z") , ISODate("2018-12-18T20:16:28.800Z"), ISODate("2016-11-14T10:16:32.700Z")], [ISODate("2016-11-14T10:16:32.700Z"), ISODate("2017-09-17T11:16:54.500Z"), ISODate("2018-12-18T20:16:28.800Z")], [ISODate("2017-09-17T11:16:54.500Z"), ISODate("2018-12-18T20:16:28.800Z"), ISODate("2016-11-14T10:16:32.700Z")] ], "bar": [ [2,5,9,8], [6,3,7,null], [7,8,null] ] }
运行上述管道后,会得到符合预期的输出:
{ "time" :[ ISODate("2018-12-18T20:16:28.800Z"), ISODate("2018-12-18T20:16:28.800Z"), ISODate("2016-11-14T10:16:32.700Z"), ISODate("2016-11-14T10:16:32.700Z"), ISODate("2017-09-17T11:16:54.500Z"), ISODate("2018-12-18T20:16:28.800Z"), ISODate("2017-09-17T11:16:54.500Z"), ISODate("2018-12-18T20:16:28.800Z"), ISODate("2016-11-14T10:16:32.700Z") ], "bar": [ 2, 5, 9, 8, 6, 3, 7, 7, 8 ] }
(注:你给出的期望输出中bar数组少了一个7,应该是输入里第三个子数组的7,实际输出会包含这个值,推测是你笔误啦)
内容的提问来源于stack exchange,提问作者bc110402922
相关产品推荐
相关产品推荐

