使用couchdb创建视图,进行分组和唯一计数

时间:2013-07-18 07:33:41

标签: mapreduce couchdb

嗨我有这样的文件

{ 
  domains: "domain1.com", 
  ip: "192.168.0.1" 
}

文档可能有不同或重复的域/ ips

我想要一个给我一个

列表的视图

domain1 =>该域的唯一IP计数
domain2 =>该域的唯一IP计数
等。

我知道如何获得:

domain => ip count with this map / reduce:

 "map": "function(doc) { emit(doc.domains, 1) }",<br/>
 "reduce": "_sum"

和group = true参数

但我无法弄清楚如何获得:

domain =&gt;独特的ip计数样式列表

为任何帮助欢呼,对不起我的英语

2 个答案:

答案 0 :(得分:0)

只使用map函数编写视图,不使用reduce函数

function(doc) {
  if (doc.domains) emit(doc.domains, doc.ip);
}

然后创建一个列出唯一条目的列表函数。

function(head, req) {
  var ips = new Array();
  while (row = getRow()) {
    if (ips.indexOf(row) != -1) { 
      ips.push(row.value);
    }
  }
  send(ips.length);
}

警告:未经过测试的代码可能包含错误。

最后,在地图视图中调用list函数,并将key设置为所需的域。请注意,如果每个域都有大量IP,则此解决方案的性能不会很好。

答案 1 :(得分:0)

正如Kim所说,用CouchdDB的Map / Reduce完成整个事情几乎是不可能的(或者可能是一个非常棘手的reduce函数)。

但是,为了获得比Kim的解决方案更好的性能,您至少可以使用Map / Reduce执行重复数据删除部分。

所以,首先使用map索引(域,ip)对(值不重要):

function(o) {
  emit([o.domain, o.ip], null);
}

然后reduce使用内置函数:

_count

现在,使用list计算唯一的ips:

function(head, req) {
  var domains = {};
  while (row = getRow()) {
    var d = row.key[0];
    if (d in domains) {
      domains[d]++;
    } else {
      domains[d] = 1;
    }
  }
  send(JSON.stringify(domains));
}

当您调用它时,请使用group=true进行查询。

注意:我没有测试过列表的代码,因此您可能需要稍微调整一下。