MongoDB聚合嵌套数据

问题描述 投票:1回答:2

我有嵌套数据如下,

{
"_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

node.js mongodb mongoose aggregation-framework
2个回答
3
投票

这应该让你去:

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
        }
    }
}])

0
投票

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

注意:这只适用于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
])
© www.soinside.com 2019 - 2024. All rights reserved.