CouchDB视图 - 将重复键值减少/分组到数组

时间:2013-04-30 11:56:26

标签: mapreduce couchdb

我在我的沙发数据库上有一个视图,它以这种格式输出数据:

{"rows":[
{"key":["Partner1","Voucher Type 1"],"value":true},
{"key":["Partner1","Voucher Type 2"],"value":true},
{"key":["Partner2","Voucher Type 1"],"value":true},
{"key":["Partner3","Voucher Type 1"],"value":true},
{"key":["Partner4","Voucher Type 1"],"value":true}
]}

我想要做的是有效地'合作'合作伙伴|凭证类型, 所以在上面的例子中,它将返回类似于:

Partner1: ["Voucher Type 1", "Voucher Type 2"]
Partner2: ["Voucher Type 1"]
Partner3: ["Voucher Type 1"]
Partner4: ["Voucher Type 1"]

目前,我的地图缩小功能如下所示:

地图:

function(
    emit([doc.PartnerName, doc.VoucherType], 1);
}

减少

function(keys, values) {
    return true;
}

我正在查询group=true

我怀疑我需要在reduce函数中做更多的事情吗?

3 个答案:

答案 0 :(得分:2)

您的目标不是减少数据量,只是为了改变格式。 所以不要使用reduce函数,请使用list function

function(head, req) {
    var lastKey, row, dedup;

    while (row = getRow()) {
        if (row.key !== lastKey) {
            dedup = {};
            send('\n' + row.key + ': ');
        }

        if (!dedup[row.value]) {
            if (row.key === lastKey) {
                send(', ');
            }

            dedup[row.value] = true;
            send(row.value);
        }

        lastKey = row.key;
    }
}

这个只是给你一个明文列表,但你可以添加你想要的任何格式,例如JSON。

Partner1: Voucher Type 1, Voucher Type 2
Partner2: Voucher Type 1

如果您不需要重复数据删除,那么它就更简单了。

答案 1 :(得分:1)

考虑以下设计文档:

{
   "_id": "_design/ddoc",
   "views": {
       "partners": {
           "map": function(doc) {
                      emit(doc.PartnerName, doc.VoucherType);
                  },
           "reduce": function(keys, values) {
                         var voucherTypes = [];
                         values.forEach(function(v) {
                             voucherTypes = voucherTypes.concat(v);
                         });
                         return voucherTypes;
                     }
       }
   }
}

你可以做的是使用group=true参数的reduce函数,即

<couchdb>/<database>/_design/ddoc/_view/partners?group=true

会给你这样的东西:

{"rows":[
{"key":"Partner1","value":["Voucher Type 2","Voucher Type 1"]},
{"key":"Partner2","value":["Voucher Type 1"]},
{"key":"Partner3","value":["Voucher Type 2"]}
]}

但是,这是相当不鼓励的,因为您正在reduce函数中构建数据结构。减少函数应该返回简单的,通常是数值。此外,上述reduce函数可能会在rereduce情况下中断。我没有测试过这个。作为替代方案,我可以建议仅使用map函数来实现查询,即

<couchdb>/<database>/_design/ddoc/_view/partners?reduce=false&key="Partner1"

会返回:

{"total_rows":4,"offset":0,"rows":[
{"id":"97c7ee4d90f57407bb1f4f680d20967b","key":"Partner1","value":"Voucher Type 1"},
{"id":"97c7ee4d90f57407bb1f4f680d20a049","key":"Partner1","value":"Voucher Type 2"}
]}

答案 2 :(得分:1)

我通过使用以下reduce来实现它:

function(keys, values, rereduce){
  var item = {};
  r=[];

  values.forEach(function(value){
    item[value] = value;
  });

  for(var i in item){
    r.push(item[i]);
  }

  return r; 
}

欢迎评论,如果这不正确,但它会以所需的格式返回数据:

PartnerName: VoucherType[]