2012-06-27 51 views
0

時間這是從這個問題How to merge objects attributes from reduce to rereduce function in CouchDB合併對象的屬性,每個視圖中創建

跟進我已經從以前的問題,接受的答案如下導致錯誤的值。要快速,這是我的JSON模式:

{"emp_no": .., 
"salary": .., 
"from_date": .., 
"to_date": .., 
"type" : "salaries"} 

{"emp_no": .., 
"title": .., 
"from_date": .., 
"to_date" : .., 
"type" : "titles"} 

我想找出每個活動標題的平均工資(由「FROM_DATE」 =「9999-01-01」表示)。由於rereduce的輸出必須是一樣的減少一個,該值將在

{"Title":[sum,count],"Title":[sum,count]} 

基於該窗體上的形式,我改變了減少功能從以前的問題,到此:

function(keys, values, rereduce) { 
    function isArray(o) { 
     return Object.prototype.toString.call(o) === '[object Array]'; 
    } 
    var i, l, sal, count, rv = {}, kobj; 
    if (rereduce) { 
     for (i = 0, l = values.length; i<l ; ++i) { 
      if (i === 0) { 
       for (kobj in values[i]) { 
        if(values[i].hasOwnProperty(kobj)) { 
         if (isArray(values[i][kobj])) { 
          rv[kobj] = values[i][kobj]; 
         } 
        } 
       } 
      } else { 
       for (kobj in values[i]) { 
        if(values[i].hasOwnProperty(kobj)) { 
         if (isArray(values[i][kobj])) { 
          sal = values[i][kobj][0]; 
          count = values[i][kobj][1]; 
          if (rv.hasOwnProperty(kobj) && isArray(rv[kobj])) { 
           rv[kobj][0] += sal; 
           rv[kobj][1] += count; 
          } else { 
           rv[kobj] = [sal,count]; 
          } 
         } 
        } 
       } 
      } 
     } 
    } else { 
     var t; 
     for (i = 0, l = values.length; i<l ; i++) { 
      switch (values[i][0]) { 
       case "title" : 
        rv[values[i][1]] = null; 
        t = i; 
        break; 
       case "salary": 
        rv[values[t][1]] = [values[i][1], 1]; 
        break; 
       default: 
        rv[values[t][1]] = null; 
        break; 
      } 
     } 
    } 
    return rv; 
} 

這裏是減小的值:http://i.imgur.com/WbmxL.png

這裏是當施加rereduce步驟的值:

{Senior Engineer: [417153, 6], Engineer: [171293, 3], Assistant Engineer: [66313, 1], Senior Staff: [248397, 3], Technique Leader: [134222, 2], Staff: [72527, 1]} 

是什麼讓我感到困惑,是每次創建視圖時,重新降低的值總是變化!即使我在函數的最後添加了註釋(//)。而且,生成的值始終是錯誤的。這裏的觀點是重建後的值:

{Senior Engineer: [540708, 7], Senior Staff: [179364, 2], Engineer: [488026, 6], Staff: [174196, 3], Assistant Engineer: [66313, 1], Technique Leader: [120310, 2]} 

我真的糊塗了,幾乎失明,因爲我不知道該怎麼做調試和後續的MapReduce功能,在CouchDB中執行。有人可以在JavaScript/MapReduce專家幫助我指出什麼是錯的?

這是我的薪水和職位文件。每個包含1000個文檔,可以使用HTTP BULK API將其插入到CouchDB中https://docs.google.com/open?id=0B2o1vMJ7XFKydUxGR3R3NU9QOEE

回答

1

您正在依靠相鄰記錄存在。您無法預測Couch如何將其傳遞到縮減功能的值集合分割。你絕對會被稱爲與分裂發生標題工資紀錄爲同一名僱員。這意味着在給定的縮減函數調用中,您將擁有一個頭銜但不是薪水,反之亦然。

我不認爲有什麼辦法來做你想用你當前的數據結構。您應該在客戶端進行平均計算,或更改您的文檔結構,以便將薪水和標題存儲在同一文檔中(後者將作爲我的方法)。

+0

這是CouchDB MapReduce的限制,還是真的如何實現?似乎我做了一個非常瘋狂的猜測,然後由此產生的中間縮小值總是按鍵排序... ... –

+0

CouchDB如何減少工作。它將基於B樹的視圖中的值分開,然後將這些值分批傳遞給reduce函數。然後,當每個批次都傳遞給reduce時,它會將結果傳回到使用'rereduce = true'的reduce中。 因此,您不能**依賴於給定縮減函數調用中存在的整個數據集。 – smathy

+0

我想你是對的。我犯了一個錯誤,認爲減少步驟產生的價值將被存儲在磁盤中,然後rereduce步驟將簡單地反饋這些值。我現在明白,相鄰的文檔並不總是存在,並且每次創建視圖時Reduce執行的順序都會有所不同。非常感謝smathy! –