MongoDB聚合合并两个等长数组为对象数组(unwind报错解决)
MongoDB同索引数组合并聚合方案
问题场景
使用$unwind聚合阶段处理数组配对时出现错误,输入集合数据结构如下:
[ { "_id": "767", "customId": [ "growth", "fine" ], "length": [ 1526, 95 ] }, { "_id": "66", "customId": [ "height", "good" ], "length": [ 86, 68 ] } ]
期望输出为两个数组同索引元素配对组成merged对象数组,保留_id字段,移除原数组字段,结构如下:
[ { "_id": "767", "merged": [ { "customId": "growth", "length": 1526 }, { "customId": "fine", "length": 95 } ] }, { "_id": "66", "merged": [ { "customId": "height", "length": 86 }, { "customId": "good", "length": 68 } ] } ]
错误原因
直接对customId、length分别执行$unwind会产生笛卡尔积:两个长度为2的数组会拆分出4条无关组合,无法实现同索引配对。
正确聚合实现
Mongo Shell执行代码
db.your_collection.aggregate([ { $set: { merged: { $map: { // 按索引对位合并两个数组 input: { $zip: { inputs: ["$customId", "$length"] } }, as: "indexPair", // 把每一组对位元素组装成目标对象 in: { customId: { $arrayElemAt: ["$$indexPair", 0] }, length: { $arrayElemAt: ["$$indexPair", 1] } } } } } }, // 删除原数组字段,匹配输出结构 { $unset: ["customId", "length"] } ])
Postman测试请求配置
- 请求方法:
POST - 请求地址:
http://<你的MongoDB HTTP服务地址>/<数据库名>/<集合名>/aggregate - 请求体选择
raw->JSON格式,传入以下内容:
{ "pipeline": [ { "$set": { "merged": { "$map": { "input": { "$zip": { "inputs": ["$customId", "$length"] } }, "as": "indexPair", "in": { "customId": { "$arrayElemAt": ["$$indexPair", 0] }, "length": { "$arrayElemAt": ["$$indexPair", 1] } } } } } }, { "$unset": ["customId", "length"] } ], "cursor": {} }
发送请求即可得到符合要求的返回结果。
关键算子说明
$zip:接收多个数组作为输入,将相同索引位置的元素打包为子数组,天然避免笛卡尔积问题$map:遍历打包后的子数组集合,逐组组装为要求的对象结构$unset:移除不需要的原始字段,简化输出结构
内容的提问来源于stack exchange,提问作者bihari atal
相关产品推荐
相关产品推荐

