2011-03-09 82 views
3

我有一個CouchDB數據庫,其視圖的值是成對的[x,y]形式的數字。對於具有相同密鑰的文檔,我需要(同時)計算x的最小值和y的最大值。我正在使用的數據庫包含大約50000個文檔。建設視圖需要幾個小時,這似乎有點過分。 (這些鍵本身就是長度爲三的數組。)我在下面顯示地圖和縮小函數,但最基本的問題是:如何加快此過程?使用CouchDb map/reduce的不同數組組件的最小和最大速度?

請注意,內置函數將不起作用,因爲值必須是數字,而不是長度爲二的數組。我可能會做出兩種不同的觀點(一種是min(x),另一種是max(y)),但我不清楚如何將它們結合起來同時得到兩個結果。

我現在的地圖功能基本上是這樣

function(doc) { 
    emit ([doc.a, doc.b, doc.c], [doc.x, doc.y]) 
} 

和我的降低函數看起來像

function(keys, values) { 
    var x = null; 
    var y = null; 
    for (i = 0; i < values.length; i++) { 
    if (values[i][0] == null) break; 
    if (values[i][1] == null) break; 
    if (x == null) x = values[i][0]; 
    if (y == null) y = values[i][1]; 
    if (values[i][0] < x) x = values[i][0]; 
    if (values[i][1] > y) y = values[i][1]; 
    } 
    emit([x, y]); 
} 

回答

1

事實證明,這是兩個因素的結合。在上面的代碼中顯而易見的是,當它使用「返回」時使用「發射」。

另一個因素不太明顯,只有通過製作較小版本的數據庫並記錄reduce函數中的步驟才能找到其他因素。雖然「值」中的條目是整數,但它們被CouchDB當作字符串處理。使用parseInt函數可以糾正這個問題。

經過這兩個修正後,縮小視圖的整個構建花了大約五分鐘,所以速度問題蒸發了。

2

只是兩個注意事項。使用Math.max()和Math.min()應該快一點。

function(keys, values) { 
    var x = -Infinity, 
     y = Infinity; 
    for (var i = 0, v; v = values[i]; i++) { 
    x = Math.max(x, v[0]); 
    y = Math.min(y, v[1]); 
    } 
    return [x, y]; 
} 

如果CouchDB將值視爲字符串,那是因爲您將它們作爲字符串存儲在文檔中。

希望它有幫助。

+0

我沒有試過Math.max,因爲我不確定它是如何處理null的。 (我在R中工作了很多,其中最接近的null值是NA,它吸收了算術運算中的所有數字。)然而,運行測試證實Math.max忽略了空值,在這裏工作也是如此。 – 2011-03-10 19:54:29

+0

不完全。 Math.max不會忽略空值,它將它視爲0.例如:「Math.max(null,1)== 1」,「Math.max(null,-1)== 0」。以下所有測試均爲真:「-1 -1」和「null> = 0」。這就是爲什麼我使用-Infinity作爲初始值。 – 2011-03-10 22:32:59