2014-11-06 59 views
2

我有一個數據庫在沙發上有55,000,000文檔。 許多文檔對某些屬性具有重複值,我想只爲屬性計算唯一值。計數couchdb行只有唯一

我是新來的couchdb和看到列表功能,但這太慢了迭代超過55萬行和超時。

如果我做的:

"map": "function(doc) { if (doc.property) { emit(doc.property, 1); } }" "reduce": "_count"

,然後組,我得到的財產,包括重複的總數。 我怎樣才能把這個減少到唯一?

謝謝。

回答

0

你的地圖功能沒問題 - 你不能在這裏做得更好。讓我們着重於減少。

function(keys, values) { 
    var result = {}; 
    var counter = 0; 
    keys.forEach(function(key) { 
    if (!result[key]) { 
     result[key] = true; // or whatever 
     counter++; 
    } 
    }); 

    return counter; 
} 
+0

你讓我走在正確的軌道上,謝謝。爲了清晰起見,我發佈了修改的代碼 – 2014-11-10 10:33:02

0
function(keys, values) { 
    var result = []; 
    keys.forEach(function(key) { 
     if (result.indexOf(key[0]) == -1) { 
      result.push(key[0]); 
     } 
    }); 

    return result.length; 
} 
0

我希望沒有人在使用公認的答案從這裏的Mariusz因爲它不工作,至少在CouchDB中

CouchDB的減少功能還需要執行rereduces。這是減少其他幾個減少的產出。

典型解決方案 使您的地圖功能輸出一個唯一的關鍵,然後減少_count。完全是你在你的問題中提出的建議,除了group = true。 這將計算每個獨特的事物有多少個實例。每一行代表一個獨特的事物。您可以輕鬆地統計列表函數中的總行數。

或者 您可能不希望讓唯一的密鑰例如,你可能有時間序列數據,並希望在一定時間範圍內查詢的唯一值,那麼你必須包括在關鍵的日期時間。 要處理這種情況是棘手的。

選項1: 天真的解決方案是不計的獨特價值,但只是讓獨特的價值觀有點像這樣的一個大名單,再算上他們都在客戶端,或在列表功能之後。

function (keys, values, rereduce) { 

    var unique = {}; 

    var getUniqueValues = function(values) { 
     for (i = 0; i < values.length; i++) { 
      if (values[i] in unique) { 
      } else { 
       unique[values[i]] = null; 
      } 
     } 
    } 

    if (rereduce === true) { 
     for (j = 0; j < values.length; j++) { 
      getUniqueValues(values[j]); 
     }; 
     return Object.keys(unique); 
    } else { 
     getUniqueValues(values); 
     return Object.keys(unique); 
    } 

} 

選項2: 另一種選擇是不降低在所有,只是在一個列表功能計數的獨特價值。正如你所說,當有很多值時,這可能會變得緩慢。

選項3: 爲了避免當計數了大量獨特的東西是棘手的使用過多的內存。 它可以通過將位圖上的唯一值散列到位來完成。 然後計算最終位圖中有多少個1。

這也讓你使用減少功能,因爲你可以結合位圖來結合你的獨特結果。然後,最後在客戶端或列表函數中計算位圖中的1。

我還沒有在CouchDB中嘗試這種呢,但理論是合理的:http://highscalability.com/blog/2012/4/5/big-data-counting-how-to-count-a-billion-distinct-objects-us.html

一個需要注意的是,如果該位是不是足夠大,有可能是一個小錯誤。但是,當您計算的數量非常大時,通常可以接受一個小錯誤。