2013-07-17 130 views
1

我試圖聚合使用部門和狀態的員工來計算每個狀態的總和。從這:MongoDB聚合多個鍵

{ 
    name : "Employee_1", 
    department: "hr", 
    status : "exist" 
}, 
{ 
    name : "Employee_2", 
    department: "acme", 
    status : "absent" 
}, 
{ 
    name : "Employee_3", 
    department: "acme", 
    status : "absent" 
} 
... 

這樣:

{ 
    department: "hr", 
    statuses: { 
    exist: 1, 
    absent: 0 
    } 
}, 
{ 
    department: "acme", 
    statuses: { 
    exist: 0, 
    absent: 2 
    } 
} 
... 

我嘗試通過做到這一點:

Employee.aggregate( 
     { $group: { 
      _id: '$department', 
      statuses: { $addToSet: "$status" } 
     }}, 
     { $project: { _id: 1, statuses: 1 }}, 
     function(err, summary) { 
      console.log(summary); 
     } 
    ); 

我只得到狀態的陣列,通過 「$ addToSet」 製作:

{ 
    department: "hr", 
    statuses: [ 
     'exist', 
     'absent' 
    ] 
}, 
{ 
    department: "acme", 
    statuses: [ 
     'exist', 
     'absent' 
    ] 
} 
... 

如何正確爲每個sta放置「{$ sum:1}」 tuses?感謝你的回覆。

回答

1

如果可能的狀態僅存在且不存在,則可以將$cond運算符與$eq運算符一起使用。

{ 
    $group : { 
     _id : '$department', 
     exist : { $sum : { $cond : [ { $eq : ['$status', 'exist'] } ,1,0 ] } }, 
     absent : { $sum : { $cond : [ { $eq : ['$status', 'absent'] } ,1,0 ] } } 
    } 
} 

分組後,你能設想,只要你想

1

mapReduce可以用來解決問題。

1)定義以下映射函數

var mapFunction = function() { 
    var key = this.department; 
    var nb_match_bar2 = 0; 
    var status_exist = 0; 
    var status_absent = 0; 
    if(this.status=="exist"){ 
    status_exist = 1; 
    }else{ 
    status_absent= 1; 
    } 
    var value = { 
    department: this.department, 
    statuses:{ 
     exist: status_exist, 
     absent: status_absent 
    } 
    }; 

    emit(key, value); 
}; 

2)限定的減少功能

var reduceFunction = function(key, values) { 

    var reducedObject = { 
    department: key, 
    statuses: { 
     exist: 0, 
     absent:0 
    } 
    }; 
    values.forEach(function(value) { 
    reducedObject.statuses.exist += value.statuses.exist; 
    reducedObject.statuses.absent += value.statuses.absent; 
    } 
); 
    return reducedObject; 
}; 

3)運行mapduce並將結果存儲在收集map_reduce_result

db.rien.mapReduce(mapFunction, reduceFunction, {out:'map_reduce_result'}) 

4)最後,查詢集合map_reduce_result

db.map_reduce_result.find() 

爲了您的集合,它應該給這樣的事情

{ 
    "_id" : "acme", 
    "value" : { 
     "department" : "acme", 
     "statuses" : { 
     "exist" : 0, 
     "absent" : 2 
     } 
    } 
} 
{ 
    "_id" : "hr", 
    "value" : { 
     "department" : "hr", 
     "statuses" : { 
     "exist" : 1, 
     "absent" : 0 
     } 
    } 
} 

,你可以輕鬆地定製。

我希望它有幫助。