【问题标题】:How to flatten JSON result from aggregation output如何展平来自聚合输出的 JSON 结果
【发布时间】: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 
    }
] 

【问题讨论】:

    标签: javascript node.js mongodb mongoose aggregation-framework


    【解决方案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 我没有得到输出,所以如果你可以在聚合中编写总查询
    猜你喜欢
    • 1970-01-01
    • 2020-07-10
    • 2018-09-27
    • 2016-05-12
    • 2013-02-16
    • 2016-08-28
    • 1970-01-01
    • 2010-11-17
    相关资源
    最近更新 更多