【问题标题】:CouchDB view - reduce / group duplicate key values to arrayCouchDB 视图 - 将重复的键值减少/分组到数组
【发布时间】:2013-04-24 08:09:36
【问题描述】:

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

{"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"]

目前,我的 map reduce 函数如下所示:

地图:

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

减少:

function(keys, values) {
    return true;
}

我正在使用group=true查询

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

【问题讨论】:

    标签: mapreduce couchdb


    【解决方案1】:

    您的目标不是减少数据量,而是改变格式。 所以不要使用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
    

    如果你不需要去重,那就更简单了。

    【讨论】:

      【解决方案2】:

      我通过使用以下 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[]
      

      【讨论】:

      • 参数values 在函数签名中出现了两次,这可能不是有意的。我不清楚您是否想要具有唯一值,这可能是您希望通过将 values 数组转换为 item 对象来实现的。无论如何,我想您将不得不单独考虑 rereduce 情况,否则您将在 items 对象中使用数组键。
      • 如果您想更好地可视化您的数据,请将 r = r.push(item[i]); 更改为 r = r.concat(i);
      【解决方案3】:

      考虑以下设计文档:

      {
         "_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 函数应该返回简单的,通常是数值。此外,上述 reduce 函数可能会在 rereduce 情况下中断。我没有测试过这个。作为替代方案,我可以建议仅使用地图功能实现查询,即

      <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"}
      ]}
      

      【讨论】:

      • 问题是,可能有一百万个文档,所以它会输出一百万行。我正在尝试获取(基本上)名称:VoucherType[](就像 group=true 的第一个想法)
      • 使用第一个选项,我得到“减少输出必须更快地缩小”
      • 啊,我担心会发生这种情况。基本上,这告诉您我在答案中显示的 reduce 函数是一个坏主意。您可以将配置中的字段reduce_limit 更改为false,但我认为您最好不应该。另见:grokbase.com/t/couchdb/user/12cb1kk47v/…
      • 在这种情况下,您绝对不应该这样做,因为数据的大小根本没有减少。运行 map-reduce 效率会非常低。
      猜你喜欢
      • 2012-03-09
      • 2012-10-05
      • 1970-01-01
      • 2020-05-31
      • 2019-01-26
      • 2023-03-08
      • 1970-01-01
      • 2016-10-02
      • 2019-03-21
      相关资源
      最近更新 更多