我希望没有人在这里使用 Mariusz 接受的答案,因为它不起作用,至少在 couchDB 中
CouchDB reduce 函数也需要执行 rereduce。那就是减少其他几个减少的输出。
典型解决方案
让你的map函数输出一个唯一的key,然后用_count做reduce。正是您在问题中提出的建议,除了 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。
这也允许您使用 reduce 函数,因为您可以组合位图来组合您独特的结果。然后最后在客户端或列表函数中计算位图中的 1。
我还没有在 couchdb 中尝试过,但理论是合理的:http: //highscalability.com/blog/2012/4/5/big-data-counting-how-to-count-a-billion-distinct-对象-us.html
需要注意的是,如果位图不够大,可能会出现小错误。但是,当您计算非常大的数量时,通常可以接受一个小的错误。