【问题标题】:MongoDB aggregate on Nested dataMongoDB 在嵌套数据上聚合
【发布时间】:2018-05-31 14:33:44
【问题描述】:

我有如下嵌套数据,

{
"_id" : ObjectId("5a30ee450889c5f0ebc21116"),
"academicyear" : "2017-18",
"fid" : "be02",
"fname" : "ABC",
"fdept" : "Comp",
"degree" : "BE",
"class" : "1",
"sem" : "8",
"dept" : "Comp",
"section" : "Theory",
"subname" : "BDA",
"fbValueList" : [ 
    {
        "_id" : ObjectId("5a30eecd3e3457056c93f7af"),
        "score" : 20,
        "rating" : "Fair"
    }, 
    {
        "_id" : ObjectId("5a30eefd3e3457056c93f7b0"),
        "score" : 10,
        "rating" : "Fair"
    }, 
    {
        "_id" : ObjectId("5a337e53341bf419040865c4"),
        "score" : 88,
        "rating" : "Excellent"
    }, 
    {
        "_id" : ObjectId("5a337ee2341bf419040865c7"),
        "score" : 75,
        "rating" : "Very Good"
    }, 
    {
        "_id" : ObjectId("5a3380b583dde50ddcea350e"),
        "score" : 72,
        "rating" : "Very Good"
    }
]
},
{
    "_id" : ObjectId("5a3764f1bc19b77dd9fd9a57"),
    "academicyear" : "2017-18",
    "fid" : "be02",
    "fname" : "ABC",
    "fdept" : "Comp",
    "degree" : "BE",
    "class" : "1",
    "sem" : "5",
    "dept" : "Comp",
    "section" : "Theory",
    "subname" : "BDA",
    "fbValueList" : [ 
        {
            "_id" : ObjectId("5a3764f1bc19b77dd9fd9a59"),
            "score" : 88,
            "rating" : "Excellent"
        }, 
        {
            "_id" : ObjectId("5a37667aee64bce1b14747d2"),
            "score" : 74,
            "rating" : "Good"
        }, 
        {
            "_id" : ObjectId("5a3766b3ee64bce1b14747dc"),
            "score" : 74,
            "rating" : "Good"
        }
    ]
}

我们正在尝试使用它来执行聚合,

db.fbresults.aggregate([{$match:{academicyear:"2017-18",fdept:'Comp'}},{$group:{_id: {fname: "$fname", rating:"$fbValueList.rating"},count: {"$sum":1}}}])

我们得到类似的结果,

{ "_id" : { "fname" : "ABC", "rating" : [ "Fair","Fair","Excellent","Very Good", "Very Good",  "Excellent", "Good", "Good" ] }, "count" : 2 }

但我们期待的结果是,

{ "_id" : { "fname" : "ABC", "rating_group" : [ 
        { 
            rating: "Excellent"
            count: 2 
        },
            { 
            rating: "Very Good"
            count: 2 
        },
            { 
            rating: "Good"
            count: 2 
        },
            { 
            rating: "Fair"
            count: 2 
        },

    ] }, "count" : 2 }

我们希望通过他们的姓名和在该组中的评分响应和评分计数来获取各个教师组。

我们已经尝试过这个,但我们没有结果。 Mongodb Aggregate Nested Group

【问题讨论】:

  • 你使用的是哪个 mongo 版本?

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

这应该可以帮助您:

db.collection.aggregate([{
    $match: {
        academicyear: "2017-18",
        fdept:'Comp'
    }
}, {
    $unwind: "$fbValueList" // flatten the fbValueList array into multiple documents
}, {
    $group: {
        _id: {
            fname: "$fname",
            rating:"$fbValueList.rating"
        },
        count: {
            "$sum": 1 // this will give us the count per combination of fname and fbValueList.rating
        }
    }
}, {
    $group: {
        _id: "$_id.fname", // we only want one bucket per fname
        rating_group: {
            $push: { // we push the exact structure you were asking for
                rating: "$_id.rating",
                count: "$count"
            }
        },
        count: {
            $avg: "$count" // this will be the average across all entries in the fname bucket
        }
    }
}])

【讨论】:

  • 感谢您的回答。它给了我想要的结果。再次感谢。 +1
【解决方案2】:

这是一个很长的聚合管道,可能有一些不必要的聚合,所以请检查并丢弃无关的。

注意:这仅适用于Mongo 3.4+

您需要使用$unwind,然后使用$group$push 评分及其计数。

matchAcademicYear = {
    $match: { 
        academicyear:"2017-18", fdept:'Comp' 
    }
}

groupByNameAndRating = {
    $group: {
        _id: { 
            fname: "$fname", rating:"$fbValueList.rating"
        },
        count: {
            "$sum":1
        }
    }
}

unwindRating = {
    $unwind: "$_id.rating"
}

addFullRating = {
    $addFields: {
        "_id.full_rating": "$count"
    }
}

replaceIdRoot = {
    $replaceRoot: {
        newRoot: "$_id"
    }
}


groupByRatingAndFname = {
    $group: {
        _id: {
            "rating": "$rating",
            "fname": "$fname"
        },
        count: {"$sum": 1},
        full_rating: {"$first": "$full_rating"}
    }
}

addFullRatingAndCount = {
    $addFields: {
        "_id.count": "$count",
        "_id.full_rating": "$full_count"
    }
}

groupByFname = {
    $group: {
        _id: "$fname",
        rating_group: { $push: {rating: "$rating", count: "$count"}},
        count: { $first: "$full_rating"}
    }    
}

db.fbresults.aggregate([
    matchAcademicYear, 
    groupByNameAndRating, 
    unwindRating, 
    addFullRating, 
    unwindRating, 
    replaceIdRoot, 
    groupByRatingAndFname, 
    addFullRatingAndCount, 
    replaceIdRoot, 
    groupByFname
])

【讨论】:

    猜你喜欢
    • 2017-07-26
    • 2021-03-13
    • 1970-01-01
    • 2021-06-27
    • 2017-07-16
    • 2019-07-20
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    相关资源
    最近更新 更多