2012-10-12 105 views
2

我想彙總一些我在CouchDB中的數據。數據庫中有照片文檔,數據庫中有評分文檔。每個等級的文檔看起來像這樣(沒有_id和_rev):如何使用CouchDB的reduce()函數?

{ 
    "type": "rating", 
    "rating": 3 // Integer values are identifiers that map to a string; e.g 1 might mean 'funny' 
    "photo": "as9i83ufsafa09uj" // The id of the photo that this rating points to. 
} 

我想要做的是讓每一個評價類型爲每張照片的數量。

{ 
    "key": "as9i83ufsafa09uj", "value": [1, 7, 8, 6] // 1 '0' rating, 7 '1' ratings, etc. 
    "key": "photoid2", "value": [3, 0, 0, 8] 
} 

我正在使用CouchDB視圖的MapReduce來實現這種聚合。

"map": "function(doc) { 
    if(doc.type == 'rating') 
    { 
     emit(doc.photo, doc.rating); 
    } 
}", 

"reduce": "function(keys, values, rereduce) { 
    var result = new Array(0, 0, 0, 0); 

    values.forEach(function(key, value) 
    { 
     result[value]+=1; 
    }); 

    return result; 
}" 

地圖返回:

{"total_rows":55,"offset":0,"rows":[ 
{"id":"0aa2c4c9a031eedbcf2795cabc1679be","key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":0}, 
{"id":"29f363432e008f5934b4160292e18680","key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":3}, 
{"id":"646d0d764623bc2f3ed1354ac03b583e","key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":2}, 
... 
{"id":"fa5be78402171e3bf1eb1cf91c5fda6e","key":"c63b78b6-ad92-426c-ab64-c9a6ae229b31","value":1} 
]} 

的減少WITB group_level返回= 0:

{"rows":[ 
{"key":null,"value":[1,1,1,1]} 
]} 

與group_level = 1:

{"rows":[ 
{"key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":[2,2,2,0]}, 
{"key":"5ad3de4b-d25b-42d3-95e0-df7661becbf3","value":[2,2,2,2]}, 
{"key":"7600710b-9ae3-4312-876c-ad352722dac3","value":[2,2,2,2]}, 
{"key":"959f48a2-5018-4938-aab4-086d8824dd75","value":[2,0,0,0]}, 
{"key":"c63b78b6-ad92-426c-ab64-c9a6ae229b31","value":[2,2,2,2]} 
]} 

我熟悉MongoDB的地圖縮小和這個功能n會使用他們的模式。我需要做些什麼才能在CouchDB中工作?

UPDATE 這是最後的減少功能,爲我工作。我沒有正確處理rereduce參數。感謝MarcinSkórzewski幫助我更好地理解rereduce。

"reduce": "function(key, values, rereduce) { 

     var result = new Array(0, 0, 0, 0); 

     if(rereduce == true) 
     { 
      for(var i = 0; i < values.length; i++) 
      { 
       var value = values[i]; 

       for (var j = 0; j < value.length; j++) 
       { 
        result[j] += value[j]; 
       } 
      } 

      return result; 
     } 

     for(var i = 0; i < values.length; i++) 
     { 
      value = values[i]; 
      result[value]+=1; 
     } 

     return result; 

     }" 

回答

2

我認爲你沒有正確使用rereducevalues元素和返回的數據不是相同的類型。如果只有一個組級別和較小的數據大小(以適應單個B-tree節點),它可以正常工作,因爲不需要運行rereduce。看看reduce docrereduce參數的含義爲reduce()

如果reduce()針對從map()發出的值運行,則它們是整數,但如果您減少之前獲得的值reduce(),則它們是數組。你可以使用rereduce,如果是true添加數組。或者你可以在地圖上發射數組(例如獲得[0,0,0,1]而不是3),並且總是在reduce()中添加數組而不必擔心rereduce參數。

相關問題