2013-04-12 153 views
1

作爲MongoDB的新手我試圖讓MapReduce調用進行。 不幸的是我得到以下錯誤:Mongo Map減少錯誤

mongos> db.events.mapReduce(m,r,"errors"); 
Fri Apr 12 11:39:15.637 JavaScript execution failed: map reduce failed:{ 
    "ok" : 0, 
    "errmsg" : "MR parallel processing failed: { errmsg: \"exception: reduce -> multiple not supported yet\", code: 10075, ok: 0.0 }" 
} at src/mongo/shell/collection.js:L970 
mongos> 

我使用蒙戈2.4.0

我的活動集合看起來是這樣的:

{ "sid" : "1UADM45MCGRTW ", "time" : ISODate("2013-04-08T11:33:13.229Z"), "class" : "S", "service" : "service1" } 
{ "sid" : "1UADM45MCGRTW ", "time" : ISODate("2013-04-08T11:33:13.229Z"), "class" : "I", "service" : "service1" } 
{ "sid" : "1UADM45MCGRTW ", "time" : ISODate("2013-04-08T11:33:13.236Z"), "class" : "E", "text" : "error message" } 
{ "sid" : "1UADM45MCGRTW ", "time" : ISODate("2013-04-08T11:33:13.239Z"), "class" : "F", "service" : "service1" } 

{ "sid" : "1UDO3H7YUOK08 ", "time" : ISODate("2013-04-08T11:33:08.095Z"), "class" : "S", "service" : "service2" } 
{ "sid" : "1UDO3H7YUOK08 ", "time" : ISODate("2013-04-08T11:33:08.095Z"), "class" : "I", "service" : "service2" } 
{ "sid" : "1UDO3H7YUOK08 ", "time" : ISODate("2013-04-08T11:33:08.173Z"), "class" : "E", "text" : "another error message" } 
{ "sid" : "1UDO3H7YUOK08 ", "time" : ISODate("2013-04-08T11:33:08.188Z"), "class" : "F", "service" : "service2" } 

{ "sid" : "1UDO3JVXIS2UZ ", "time" : ISODate("2013-04-08T11:28:39.480Z"), "class" : "I", "service" : "service1" } 
{ ""sid" : "1UDO3JVXIS2UZ ", "time" : ISODate("2013-04-08T11:28:39.480Z"), "class" : "S", "service" : "service1" } 
{ "sid" : "1UDO3JVXIS2UZ ", "time" : ISODate("2013-04-08T11:28:40.853Z"), "class" : "F", "service" : "service1" } 
{ "sid" : "1UDO3JVXIS2UZ ", "time" : ISODate("2013-04-08T11:28:40.852Z"), "class" : "I", "service" : "service1" } 

我的目的是讓所有的 「E」條目並將它們與「F」條目的相應「sid」的「服務」字段組合。所以這應該是非常簡單的,但我無法得到它(因爲上述錯誤)。

地圖/減少I使用的是功能:

var m = function() { 
    if (this.class == "E") { 
     value = { time: this.time, error: this.text }; 
     emit(this.sid, value); 
    } else if (this.class == "F") { 
     value = { service: this.service }; 
     emit(this.sid, value); 
    } 
} 


var r = function(key,values) { 
    return values; 
} 

db.events.mapReduce(m,r,"errors"); 

回答

4

問題是,你想積累每個鍵的所有錯誤,這意味着你必須發出一個文件數組,然後你的減少必須將它們組合成一個單一的數組(因爲它將接收一個數組陣列)。

您遇到的另一個問題是您想將每個獨特cid的不同類別合併爲一些組合縮減結果,但您的縮減功能甚至不會嘗試這樣做。

很難知道你可能有多少種不同的類值獲得每個SID,但如果這就像你給的例子數據,我猜你想是這樣的:

var m = function() { 
    array = []; 
    if (this.class == "E") { 
     value = { time: this.time, error: this.text }; 
     array.push(value); 
     emit(this.sid, {a:array}); 
    } else if (this.class == "F") { 
     value = { service: this.service }; 
     array.push(value); 
     emit(this.sid, {a:array}); 
    } 
} 


var r = function(key,values) { 
    result = {a:[]}; 
    values.forEach(function (v) { 
     result.a = v.a.concat(result.a); 
    }); 
    return result; 
} 

db.events.mapReduce(m,r,"errors"); 

在你的榜樣,所產生的收集將是這樣的:

> db.errors.find().pretty() 
{ 
    "_id" : "1UADM45MCGRTW ", 
    "value" : { 
     "a" : [ 
      { 
       "service" : "service1" 
      }, 
      { 
       "time" : ISODate("2013-04-08T11:33:13.236Z"), 
       "error" : "error message" 
      } 
     ] 
    } 
} 
{ 
    "_id" : "1UDO3H7YUOK08 ", 
    "value" : { 
     "a" : [ 
      { 
       "service" : "service2" 
      }, 
      { 
       "time" : ISODate("2013-04-08T11:33:08.173Z"), 
       "error" : "another error message" 
      } 
     ] 
    } 
} 
{ 
    "_id" : "1UDO3JVXIS2UZ ", 
    "value" : { 
     "a" : [ 
      { 
       "service" : "service1" 
      } 
     ] 
    } 
} 

你或許可以添加一個finalize函數,這個數組轉換成一個結果,這是一個單一的文件,但是這取決於你想有和上產生的收集格式每個sid的預期輸入。

+0

非常有幫助 - 謝謝 – pitseeker

0

根據文檔(troubleshoot reduce function) 「的降低函數必須返回一個對象,其類型必須與由射出的值的類型地圖功能

當你發射一個物體時,reduce也應該發射一個物體 - 所以把values包裹在一個物體中,你應該很好走。