MongoDB:如何计算嵌套数组的平均值

时间:2017-04-08 20:05:00

标签: arrays mongodb nested average

我想计算"成绩的平均数"来自不同的" 课程" (" IABD",NPAD" ...)通过专用函数将ID和 NAME (课程)作为参数集合文档中的参数,具有如下结构。

{
        "_id" : ObjectId("58e8ba731c9f5cc5bf605e27"),
        "ID" : 123457,
        "name" : "Stack",
        "surname" : "Overflow",
        "grades" : [
                {
                        "IABD" : [
                                2,
                                3,
                                4,
                                5
                        ]
                },
                {
                        "NPAD*" : [
                                3.5,
                                2.5
                        ]
                },
                {
                        "SIDB" : [
                                5,
                                3.5
                        ]
                },
                {
                        "NPAD" : [
                                5,
                                2
                        ]
                },
                {
                        "IABD" : [
                                4,
                                6
                        ]
                }
        ]
}

以下一个不起作用:

db.studenci.aggregate([ { $project: { courseAvg: { $avg: '$grades.NPAD'} } } ])

尝试通过以下方式获得成绩数组:

function avg(ID,course) { doc = db.collection.find({ID: ID}); doc1 = doc[0]; return doc1.grades[0]; }

但无法深入研究数组值以计算平均值......

一旦我想要制作一个简单的AVG硬编码值......

                var avg = 0 ;
                var summ = 0;
                for(var i = 0 ; i < numbers.length ; i++){
                    summ = summ + numbers[i]};
                    return summ
                    }   
                avg = summ / numbers.length;
                return avg;

我期待着你的回复。

1 个答案:

答案 0 :(得分:0)

这不是一个优雅的解决方案(我不是MongoDB的专家),但这可行(我在我的mongo本地测试):

function avgByIdAndCourse(id, course){

//THIS VARIABLE WILL STORE THE RESULT OF AVG
var res;

//REPLACE "N" WITH YOU COLLECTION NAME
db.n.find(ObjectId(id)).forEach( function(doc) {

//CREATE THE GRADES ARRAY
var arr = doc.grades;

//VARIABLE FOR AVG CALCULATION
var count = 0;

for(var i = 0; i < arr.length; i++){
    var obj = arr[i];

    //LOOP OVER GRADES KEY
    for(var key in obj){

    //IF THE COURSE MATCHES WITH OUR COURSE PARAMETER
    if(key == course){
        count = 0;

    //ARRAY OF VALUES OF COURSE
    var a = obj[key];
    for(var j = 0; j < a.length; j++){
        count += a[j];
    }
    // just a print for make sure it works ---> print(count/a.length);

    //STORE THE RESULT IN RES VARIABLE
    res = count/a.length;
    }

}
  }

  //REQUIRED BY FOREACH CALLBACK(NOT SURE ABOUT THAT)
  db.n.save(doc);
 });

//RETURN THE RESULT
return res;
}

您可以尝试优化关键部分的循环(考虑到我们不需要遍历密钥,我们只需通过尝试访问密钥来检查该密钥是否存在)。

如果您将其复制并粘贴到shell上,则可以通过以下方式对其进行测试:

var result = avgByIdAndCourse('PUTIDTOFINDHERE', 'COURSENAME');
print(result);

现在你应该看到该课程的平均值。

希望它有所帮助。