2011-03-09 78 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