能否通过Mongo的$group实现指定数据转换,还是需客户端JS处理?
用MongoDB聚合实现按id分组并将lib转为带序号的字段结构
- 完全可以通过MongoDB的聚合管道实现,不需要在客户端用JavaScript处理
核心逻辑分三步:先把同一id下的所有lib值收集成数组,再把数组转换成lib_1、lib_2这类带序号的键值对,最后把这些键值对合并到主文档里。
示例操作
假设你的原始数据是这样的:
[ { id: 1, lib: "A" }, { id: 1, lib: "B" }, { id: 2, lib: "C" }, { id: 2, lib: "D" }, { id: 2, lib: "E" } ]
执行以下聚合命令:
db.collection.aggregate([ // 按id分组,把同id的lib攒成数组 { $group: { _id: "$id", libs: { $push: "$lib" } } }, // 将数组转成lib_1、lib_2格式的键值对对象 { $addFields: { libFields: { $arrayToObject: { $map: { input: "$libs", as: "item", in: { k: { $concat: ["lib_", { $toString: { $add: [{ $indexOfArray: ["$libs", "$$item"] }, 1] } }] }, v: "$$item" } } } } } }, // 把生成的字段合并到根文档,清理临时字段 { $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$libFields"] } } }, { $project: { libs: 0, libFields: 0 } } ])
最终结果
[ { _id: 1, lib_1: "A", lib_2: "B" }, { _id: 2, lib_1: "C", lib_2: "D", lib_3: "E" } ]
额外说明
- 索引加1是为了让序号从
1开始(默认数组索引从0),如果不需要可以去掉$add里的1 - 要是想把
_id改回原来的id字段,在最后加一步:{ $addFields: { id: "$_id" }, $project: { _id: 0 } }
内容的提问来源于stack exchange,提问作者marojbor
相关产品推荐
相关产品推荐

