如何对复杂Mongo集合执行Pivot(数据透视)操作?
在MongoDB中实现数据透视操作
没问题,我帮你搞定MongoDB里的这个数据透视需求!其实用MongoDB的聚合管道就能实现,咱们一步步拆解:
核心思路
你需要把嵌套在parameters数组里的name转换为顶层字段,对应的value作为字段值,最终按date聚合出一行行的透视结果。咱们用聚合管道的几个阶段就能实现:
步骤1:拆分嵌套数组
先用$unwind把每个文档的parameters数组拆分成单个文档,这样每个文档就对应一个name-value对,方便后续分组处理:
{ $unwind: "$parameters" }
步骤2:按日期和参数名去重(可选)
如果你的数据里存在同一个日期下重复的参数名(比如同一个date里出现两次value_1),可以先按date和name分组,确保每个参数名在日期下唯一,这里用$last取最新的value,你也可以换成$first取最早的:
{ $group: { _id: { date: "$date", name: "$parameters.name" }, value: { $last: "$parameters.value" } } }
步骤3:按日期聚合参数键值对
接下来按date分组,把每个参数的name和value整理成{k: 键名, v: 数值}的格式,存入数组中:
{ $group: { _id: "$_id.date", params: { $push: { k: "$_id.name", v: "$value" } } } }
步骤4:将数组转为对象
用$arrayToObject把上一步的数组转换成键值对对象,这样参数名就变成了对象的键:
{ $addFields: { parametersObj: { $arrayToObject: "$params" } } }
步骤5:合并为最终透视文档
最后用$replaceRoot和$mergeObjects把日期字段和参数对象合并,生成顶层字段的透视结果:
{ $replaceRoot: { newRoot: { $mergeObjects: [ { date: "$_id" }, "$parametersObj" ] } } }
完整聚合命令
把上面的步骤整合起来,完整的聚合查询如下(包含去重处理):
db.your_collection_name.aggregate([ { $unwind: "$parameters" }, { $group: { _id: { date: "$date", name: "$parameters.name" }, value: { $last: "$parameters.value" } } }, { $group: { _id: "$_id.date", params: { $push: { k: "$_id.name", v: "$value" } } } }, { $addFields: { parametersObj: { $arrayToObject: "$params" } } }, { $replaceRoot: { newRoot: { $mergeObjects: [{ date: "$_id" }, "$parametersObj"] } } } ])
结果示例
运行上面的命令后,你会得到类似这样的透视文档:
{ "date": ISODate("2018-04-02T00:00:00Z"), "value_1": 50, "value_2": 25, "value_3": 20, "value_4": 15 }, { "date": ISODate("2018-04-15T00:00:00Z"), "value_5": 10 }
内容的提问来源于stack exchange,提问作者Gael Sapori
相关产品推荐
相关产品推荐

