2012-06-26 27 views
1

到rereduce功能這是我的JSON模式:如何合併對象從降低屬性CouchDB中

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

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

什麼,我想要做的,就是找到每個活動標題的平均工資。活動標題是用 「FROM_DATE」 屬性設置文件爲 「9999-01-01」

這裏是我的地圖功能

function(doc) { 
if (doc.type == 'salaries') { 
     var dateSalaries = null; 
     dateSalaries = doc.to_date.split("-"); 
     if(dateSalaries[0].localeCompare("9999") == 0){ 
      emit(doc.emp_no, ["salary", doc.salary]); 
     } 
    } else if (doc.type == 'titles') { 
     var dateTitles = null; 
     dateTitles = doc.to_date.split("-"); 
     if(dateTitles[0].localeCompare("9999") == 0){ 
      emit(doc.emp_no, ["title", doc.title]); 
     } 
    } 
} 

這裏是產生鍵值對emited:

http://i.imgur.com/o1Qxz.png

現在,我想將它縮減爲單個鍵值對,並將輸出的值設置爲這樣的javascript對象

{ 
    "engineer" : 64342, 
    "senior engineer" : 123111, 
    "staff" : ..., 
    "senior staf" : ..., 
    . 
    . 
    . 
} 

下面是我計劃如何實現它:首先,在減少步驟中,我將返回合併來自同一個emp_no的屬性的對象。然後,在減少步驟中,我將創建一個新的對象,該對象具有基於之前減少的值的屬性名稱。

這很難解釋,所以這裏我減少功能:

function(keys, values, rereduce) { 
    var i, l, attr, sal, rv = {}; 
    if (rereduce) { 
     for (i = 0, l = values.length; i<l ; ++i) { 
      if (values[i].hasOwnProperty('salary')) { 
       attr = values[i].title; 
       sal = values[i].salary; 
       if (rv[attr] instanceof Array) { 
        rv[attr].push(sal); 
       } else{ 
        rv[attr] = []; 
        rv[attr].push(sal); 
       } 
      }   
     } 

     for (var x in rv) { 
      if (rv.hasOwnProperty(x)) { 
       var totalSalary = 0; 
       for (i = 0, l = values.length; i<l ; i++) { 
        totalSalary += rv[x][i]; 
       } 
       rv[x] = totalSalary/rv[x].length; 
      } 
     } 

    } else { 
     for (i = 0, l = values.length; i<l ; i++) { 
      switch (values[i][0]) { 
       case "title" : rv["title"] = values[i][1]; break; 
       case "salary": rv["salary"] = values[i][1]; break; 
      } 
     } 
    } 
    return rv; 
} 

這裏所得到的值降低的價值,這是我所期待的: http://i.imgur.com/SnlOU.png

但是,當我設置分組價值'在'蒲團,這不是我想要的:

{Senior Engineer: null, Assistant Engineer: null, Technique Leader: null} 

有人可以幫我解決這個問題嗎?

+0

我已經改變了rereduce步驟,但仍然困擾着找到平均工資。這裏的後續問題:(http://stackoverflow.com/q/11231108/1448852) –

回答

2

您正在推動CouchDB非常接近它的極限—使用reduce函數來執行連接和一切。

您的問題來自於以下事實:CouchDB可能會應用零個,一個或多個rereduce步驟,但是您的代碼假定只執行一個rereduce步驟。我懷疑null的結果來自最終的再減少步驟應用於來自減少步驟的某些結果以及來自再減少步驟的一些結果的事實。

下面是一個小圖。 M是地圖步驟,R是縮小步驟,RR是重新縮小步驟。

[X] [X] [X] [X] [X] [X] [X] [X] [X] [X] 
| | | | | | | | | | 
(M) (M) (M) (M) (M) (M) (M) (M) (M) (M) 
| | | | | | | | | | 
(==R==) (==R==) (==R==) (==R==) (==R==) 
    |  |  |  |  | 
    (== R R ==)  (== R R ==)  | 
     |    |   | 
     (====== R R ======)   | 
       |     | 
       (======== R R ========) 
         | 
         v 
         [X] 

使用CouchDB降低的觀點,重要的是你減少步驟輸出的數據具有相同的格式由您rereduce步驟輸出的數據。尤其是,這意味着您不需要存儲平均值,而需要存儲(總和,計數)對。

+0

哇,我認爲,因爲rereduce將合併成一個kvp,我可以假設它將在數組中連續運行。我從來沒有想過,減少輸出必須是相同的減少.. 但是,我似乎無法找到任何其他方式來解決這個問題。我怎樣才能找到每個標題平均工資? –

+0

減少並重新生成「{」Title「:[sum,count],」Title「:[sum,count]}'形式的輸出字典。減少輸出只有一個標題,並且rereduce可以輕鬆地將這些字典組合在一起。平均值不會爲您計算,但您可以在客戶端輕鬆計算平均值(以總數除數)。 –

0

如果您可以將標題和薪水放在同一個員工文檔中,它會讓您的生活變得更輕鬆。

{ 
"name" : "Joe", 
"title" : "Plumber", 
"salary" : 60000 
} 

,那麼你可以很容易地與emit(doc.title, doc.salary)內置的_stats減少功能和拿不到工資統計數據爲每個標題的視圖。

+0

我試圖用不同的方法建模這個員工模式。這是一個更正常化的結構。另一個是獨立的方法。到目前爲止,自給自足比較容易.. –