2012-10-06 85 views
4

所以這很奇怪。我試圖使用MapReduce的分組日期時間/度的唯一端口下:如果請求的記錄少數MongoDB mapreduce返回'null'丟失數據

var query = { 
     'array_serial' : array, 
     'port_name' : { $in : ports }, 
     'datetime' : { $gte : from, $lte : to} 

    } 

    var map = function() { 
     emit({ portname : this.port_name } , { datetime : this.datetime, 
           metric : this.metric }); 
    } 

    var reduce = function(key, values) { 
     var res = { dates : [], metrics : [], count : 0} 

     values.forEach(function(value){ 
      res.dates.push(value.datetime); 
      res.metrics.push(value.metric); 
      res.count++; 
     }) 

     return res; 
    } 

    var command = { 
     mapreduce : collection, 
     map : map.toString(), 
     reduce : reduce.toString(), 
     query : query, 
     out : { inline : 1 } 

    } 

    mongoose.connection.db.executeDbCommand(command, function(err, dbres){ 
     if(err) throw err; 
     console.log(dbres.documents); 
     res.json(dbres.documents[0].results); 
    }) 

文檔佈局:

{ 
     "_id" : ObjectId("5069d68700a2934015000000"), 
     "port_name" : "CL1-A", 
     "metric" : "340.0", 
     "port_number" : "0", 
     "datetime" : ISODate("2012-09-30T13:44:00Z"), 
     "array_serial" : "12345" 
} 

和MapReduce功能,比如5或10,甚至60我可以獲得所有我期待的數據。較大的查詢返回截斷值....


我只是做了一些更多的測試,它好像它限制了創紀錄產量爲100? 這是詳細的數據,當我運行查詢24小時期間,我會預計返回1440條記錄...我剛剛跑了一個收到80.:\

這是預期嗎?我不指定任何地點的限制,我可以告訴...


更多的數據:

查詢的記錄從2012-10-01T23:00 - 2012-10-02T00:39(100分鐘)返回正確:

[ 
    { 
    "_id": { 
     "portname": "CL1-A" 
    }, 
    "value": { 
     "dates": [ 
     "2012-10-01T23:00:00.000Z", 
     "2012-10-01T23:01:00.000Z", 
     "2012-10-01T23:02:00.000Z", 
     ...cut... 
     "2012-10-02T00:37:00.000Z", 
     "2012-10-02T00:38:00.000Z", 
     "2012-10-02T00:39:00.000Z" 
     ], 
     "metrics": [ 
     "1596.0", 
     "1562.0", 
     "1445.0", 
     ...cut... 
     "774.0", 
     "493.0", 
     "342.0" 
     ], 
     "count": 100 
    } 
    } 
] 

...多一分鐘添加到查詢2012-10-01T23:00 - 2012-10-02T00:39(101分鐘):

[ 
    { 
    "_id": { 
     "portname": "CL1-A" 
    }, 
    "value": { 
     "dates": [ 
     null, 
     "2012-10-02T00:40:00.000Z" 
     ], 
     "metrics": [ 
     null, 
     "487.0" 
     ], 
     "count": 2 
    } 
    } 
] 

dbres.documents對象是否顯示正確的預期發出的記錄:

[ { results: [ [Object] ], 
    timeMillis: 8, 
    counts: { input: 101, emit: 101, reduce: 2, output: 1 }, 
    ok: 1 } ] 

...所以是數據取得了一些失去了什麼?

回答

10

規則數的MapReduce的一個:

你應從減少您在地圖的鑰匙發出完全相同的格式返回。

規則二的MapReduce:

你應降低,以降低作爲根據需要多次值的陣列。減少功能可能被調用很多次。

您在執行reduce時破壞了這兩個規則。

您的地圖功能正在發送鍵值對。

鍵:端口名(你應該簡單地發出名稱爲重點,而不是一個文件)
值:表示你需要積累三件事情的文件(日期,度量計)

試試這個:

map = function() { // if you want to reduce to an array you have to emit arrays 
    emit (this.port_name, { dates : [this.datetime], metrics : [this.metric], count: 1 }); 
} 

reduce = function(key, values) {  // for each key you get an array of values 
    var res = { dates: [], metrics: [], count: 0 }; // you must reduce them to one 

    values.forEach(function(value) { 
      res.dates = value.dates.concat(res.dates); 
      res.metrics = value.metrics.concat(res.metrics); 
      res.count += value.count; // VERY IMPORTANT reduce result may be re-reduced 
     }) 

     return res; 
    } 
+0

謝謝,這個幫助很大。 –

1

嘗試在臨時集合而不是內存中輸出映射減少數據。可能這就是原因。從Mongo Docs

{在線:1} - 使用此選項,沒有收藏將被創建,並 整個地圖,減少操作將在RAM中發生。此外,map-reduce的結果 將在結果對象中返回。請注意, 僅當結果集符合單個文檔的16MB 限制時纔可以使用此選項。在v2.0中,這是副本副本上唯一可用的 選項。

另外,它可能不是原因,但MongoDB在32位機器上有數據大小限制(2GB)。

+0

好的建議,我只是試了一下,而且還在截取數據。截斷的集合具有「null」作爲度量和日期數組的第一個值,我想知道這是否是一個線索。 –

+0

哦,並且具有4個端口的查詢的輸出僅爲6k,所以我並沒有真正接近16mb的限制。 –

+0

哦,那你能不能粘貼[pastebin](http://pastebin.com/)或類似的東西的數據的mongodump。 – vikas