2017-04-08 117 views
0

我想通过一个专用的函数来计算来自不同的“course”(“IABD”,NPAD“...)的”等级“的平均值,并且通过一个专用函数来计算ID和NAME(的过程),为与诸如以下的结构集合文件参数MongoDB:如何计算一个嵌套数组的平均值

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

我期待您的回复。

回答

0

这不是一个完美的解决方案(我不会MongoDB的专家),但这个工作(我在我的蒙戈本地测试):

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); 

现在你应该看到的是当然的魅力。

希望它有帮助。

+0

哇,它像一个魅力工作!非常感谢!!我不认为它会如此先进。您能否告诉我们您是否有任何关于如何将文档技术ID与作为对象属性存在的文档进行切换的建议? (在本例中为123457) – wounky

+0

正如我所说我不是专家,你应该向专家征求建议。要改变查询,你可以在find方法中写下类似的内容:{ID:id}而不是ObjectId(id)。我能否要求您提出答案,并将其标记为解决方案,如果它对您有用吗? – FFdeveloper

+0

然而,我很高兴地看到,我还没有15个声望点,请问是否有办法克服它? – wounky