如何展平来自聚合输出的 JSON 结果

Posted

技术标签:

【中文标题】如何展平来自聚合输出的 JSON 结果【英文标题】:How to flatten JSON result from aggregation output 【发布时间】:2018-09-02 23:09:02 【问题描述】:

使用 mongo db 聚合我编写了以下 NodeJs api。我得到了输出,但没有得到我的预期输出,那么如何做到这一点,谁能帮我解决这个问题?

app.get('/polute', function (req, res) 
    Light.aggregate([ 
         $match: 
            CREATE_DATE: 
                $lte:new Date(),
                $gte: new Date(new Date().setDate(new 
                    Date().getDate()-120)
                )
            
         ,
         $group: 
            _id: 
                month:  $month: "$CREATE_DATE" ,
                year:  $year: "$CREATE_DATE" 
            ,
            avgofozone:$avg:"$OZONE"
         ,
         $sort: "year": -1  ,
         $project: 
            year: '$_id.year',
            avgofozone: '$avgofozone',
            month: '$_id.month',_id:0
         
   ], function (err, polute) 
       console.log("naresh:" +JSON.stringify(polute));
        res.json(polute);
   );
);

实际输出:

[
     "avgofozone" : 21.07777777777778, "year" : 2018, "month" : 2 
     "avgofozone" : 17.8, "year" : 2018, "month" : 3 
     "avgofozone" : 17.8, "year" : 2018, "month" : 1 
]

预期输出:

[
     
        "zone_type": "avgofozone", 
        "year": 2018, 
        "February": 21.07777777777778, 
        "March": 17.8, 
        "January": 17.8 
    
] 

【问题讨论】:

【参考方案1】:

在 MongoDb 3.6 和更高版本中,您可以利用 $arrayToObject 运算符和 $replaceRoot 管道来获得所需的 JSON 输出。您需要运行以下聚合管道:

const monthsEnum = 
    "_id": "year",
    "1": "January",
    "2": "February",
    "3": "March",
    "4": "April",
    "5": "May",
    "6": "June",
    "7": "July",
    "8": "August",
    "9": "September",
    "10": "October",
    "11": "November",
    "12": "December"
;

Light.aggregate([ 
     "$match": 
        "CREATE_DATE": 
            "$lte": new Date(),
            "$gte": new Date(new Date().setDate(new Date().getDate()-120))
        
     ,
     "$group": 
        "_id":  
            "month":  "$month": "$CREATE_DATE" ,
            "year":  "$year": "$CREATE_DATE" 
        ,
        "avgofozone":  "$avg": "$OZONE" 
     ,
     "$group": 
        "_id": "$year",
        "avgs": 
            "$push": 
                "k":  "$substr": ["$month", 0, -1 ] ,
                "v": "$avgofozone"
            
        
     ,
     "$replaceRoot":  
        "newRoot":  
            "$mergeObjects": [ 
                 "$arrayToObject": "$avgs" , 
                "$$ROOT" 
             ] 
         
     ,
     "$project":  "avgs": 0  
], (err, data) => 
    console.log("naresh:" +JSON.stringify(data));
    const polute = Object.keys(data).reduce((p, c) => (...p, monthsEnum[c]: data[c]), );
    res.json(polute);
)

对于仅使用聚合管道进行整形,您可以使用 $let 运算符将月份索引映射到数组中的值。考虑运行以下管道:

const MONTHS = [, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

Light.aggregate([ 
     "$match": 
        "CREATE_DATE": 
            "$lte": new Date(),
            "$gte": new Date(new Date().setDate(new Date().getDate()-120))
        
     ,
     "$group": 
        "_id":  
            "month":  "$month": "$CREATE_DATE" ,
            "year":  "$year": "$CREATE_DATE" 
        ,
        "avgofozone":  "$avg": "$OZONE" 
     ,
     "$group": 
        "_id": "$year",
        "avgs": 
            "$push": 
                "k": 
                    "$let": 
                        "vars":  "monthsList": MONTHS ,
                        "in":  "$arrayElemAt": ["$$monthsList", "$month"] 
                    
                ,
                "v": "$avgofozone"
            
        
     ,
     "$replaceRoot":  
        "newRoot":  
            "$mergeObjects": [ 
                 "$arrayToObject": "$avgs" , 
                "$$ROOT" 
             ] 
         
     ,
     "$project":  "avgs": 0  
], (err, data) => 
    console.log("naresh:" +JSON.stringify(data));
    res.json(data);
)

【讨论】:

@chridam 任何可能的总查询只写聚合请建议我 @VARUN 我可以,你能指出我的问题的全部细节吗? @chridam 你写的查询非常正确,但输出相同,我会检查 robomongo 我没有得到输出,所以如果你可以在聚合中编写总查询

以上是关于如何展平来自聚合输出的 JSON 结果的主要内容,如果未能解决你的问题,请参考以下文章

展平来自 JSONB 字段的聚合键/值对?

生成嵌套 JSON(反向横向展平)

如何在输出中调用具有聚合结果的存储过程?

如何展平多个嵌套的 json 并转换为数据框?

展平嵌套的 JSON 对象

如何使用 flatten_json 递归地展平嵌套的 JSON