计算Couchbase视图中的唯一键

时间:2014-06-25 16:17:39

标签: map unique couchbase reduce scalar

我试图想出一种方法来计算非主键的存储桶中唯一值的数量。 Couchbase 2.5提供了一个n1ql方法来执行此操作。如果我们使用他们的啤酒样品,您可以发出以下命令:

从啤酒样本中选择计数(不同的样式)

返回标量值68.

我使用的是couchbase 2.2.0,它在技术上没有n1ql。我希望尽可能利用map / reduce / rereduce功能。原因是我拥有数百万条记录,而adhoc查询可能需要数天才能运行。有这样的方法吗?

对于地图功能,我有以下内容:

function (doc, meta) {
     if ( doc.type == "beer")
       emit(doc.style, doc.style);
}

对于reduce我有以下内容:

function(key, values, rereduce) {
    var u = {}, a = [];
    var results = {};

    if (rereduce) {

      for (var i = 0; i < values.length; i ++ ) {
        for ( var j = 0; j < values[i].length; j ++ ) {
          if (u.hasOwnProperty(values[i][j])) {
            continue;
          }

          a.push(values[i][j]);
          u[values[i][j]] = 1;
        }
      }
      return (a); 
    } else {  
      for(var i = 0; i < values.length; i++) {
        if (u.hasOwnProperty(values[i])) {
          continue;
        }

        a.push(values[i]);
        u[values[i]] = 1;
      } 
      return(a);  
  }
}

这将返回一个具有唯一值但不是标量计数的数组。我能以任何方式获得独特啤酒风格的标量数量吗?感谢。

2 个答案:

答案 0 :(得分:1)

对此的解决方案相对简单(至少对于视图而言)。

首先,没有必要输出doc / beer样式 值,因此你的map函数会更好:

function (doc, meta) {
    if (doc.type == "beer") {
        emit(doc.style, null)
    }
}

接下来,只需使用内置的_count reduce函数。

默认情况下,这只会输出您计算的存储桶中所有文档的数量,但是通过调用map函数并将过滤器参数group设置为{{ 1}}和true设置为group level(确切的方法会因客户端SDK而异)。这样做会返回一个类似如下的对象数组:

1

使用{"rows":[ {"key":null,"value":1111}, {"key":"American Rye Ale or Lager","value":11}, {"key":"American-Style Amber/Red Ale","value":219}, {"key":"American-Style Barley Wine Ale","value":32}, {"key":"American-Style Brown Ale","value":187}, {"key":"American-Style Cream Ale or Lager","value":12}, {"key":"American-Style Dark Lager","value":1}, {"key":"American-Style Imperial Stout","value":55}, {"key":"American-Style India Black Ale","value":1}, {"key":"American-Style India Pale Ale","value":230}, {"key":"American-Style Lager","value":370}, {"key":"American-Style Light Lager","value":39}, {"key":"American-Style Pale Ale","value":393}, {"key":"American-Style Stout","value":241}, {"key":"American-Style Strong Pale Ale","value":8} … … ] } 过滤器参数可以缩小此数组(键是特定样式,在这种情况下(或者您希望计算的任何内容))或类似地,您可以从中选择这个客户端。

答案 1 :(得分:0)

如果不同组的数量不会太大,请尝试在reduce函数中传递一个关联数组。

在啤酒样品桶中:

/**
 * Map function
 */
function (doc, meta) {
  if (doc.type == "beer" && doc.style)
    emit(doc.style, null);
}

/**
 * Reduce function
 */
function (keys, values, rereduce) {
  count_by_key = {};
  if (rereduce) {
    for (i in values) {
      _count_by_key = values[i];
      for (key in _count_by_key) {
        count_by_key[key] = _count_by_key[key] + (count_by_key[key] || 0);
      }
    }
  } else {
    if (keys)
      for (i in keys) {
        key = keys[i];
        count_by_key[key] = 1 + (count_by_key[key] || 0);
      }
  }
  return count_by_key; 
}

结果值中的键数是独特啤酒样式的标量数。它也适用于关键过滤器。