2014-11-06 28 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

一个需要注意的是,如果该位是不是足够大,有可能是一个小错误。但是,当您计算的数量非常大时,通常可以接受一个小错误。