2017-04-08 118 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