【问题标题】:CouchDB Map/Reduce function to get average based on group=true and then get the max average of all grouped valuesCouchDB Map/Reduce 函数根据 group=true 获取平均值,然后获取所有分组值的最大平均值
【发布时间】:2014-05-16 01:44:34
【问题描述】:

我有一个地图函数来发出时间和价值,假设我有 4 个这种格式的文档。

Doc1  ->(time1, 20)
Doc2  ->(time1, 60)
Doc1  ->(time2, 30)
Doc2  ->(time2, 15)

我需要的是按时间分组,然后得到平均值,然后返回哪个平均值更高。

所以,通过分组,我得到 A = (val1+val2)/2 和 B= (val3+val4)/2

我想检查 A 和 B 之间哪个数字更大并将其返回。因此,在上面的示例中,返回的最大值将为 A = (20+60)/2 = 40

我如何编写一个 reduce 函数来实现这一点。

【问题讨论】:

    标签: group-by mapreduce couchdb


    【解决方案1】:

    这个有点棘手,因为您要以多种方式比较多个文档中的值。这是我在短时间内的最佳尝试,我相信其他人可以对此进行改进,以使其更接近您的最终目标。

    我创建了 2 个文档:(您的示例不是很清楚,所以我做出了最好的猜测)

    {
       "times": [
           {
               "ts": 1388556000000,
               "value": 30
           },
           {
               "ts": 1391234400000,
               "value": 15
           }
       ]
    }
    
    {
       "times": [
           {
               "ts": 1388556000000,
               "value": 20
           },
           {
               "ts": 1391234400000,
               "value": 30
           }
       ]
    }
    

    我的地图函数如下所示:(基本上,对于每个文档中的每次,我都会发出它的时间戳和值)

    function(doc) {
      doc.times.forEach(function (time) {
        emit(time.ts, time.value);
      });
    }
    

    而我对应的reduce函数如下所示:

    _stats
    

    这是一个内置的 reduce 函数,它是用 Erlang 编写的,所以它的性能和效率都很高。这个特殊的reduce函数公开了关于发射值的统计信息,即maxsumcount(后两者可用于计算平均值)

    如果您使用group=true 调用此视图(隐含reduce=true),您将获得如下结果:

    {
      "rows": [
        {
          "key": 1388556000000,
          "value": {
            "sum": 50,
            "count": 2,
            "min": 20,
            "max": 30,
            "sumsqr": 1300
          }
        },
        {
          "key": 1391234400000,
          "value": {
            "sum": 45,
            "count": 2,
            "min": 15,
            "max": 30,
            "sumsqr": 1125
          }
        }
      ]
    }
    

    就像我说的,这不是一个完整的解决方案,但我打算介绍 3 个主要概念。

    1) 为单个文档发出多次 2) group=true 查看查询参数 3) 内置reduce函数

    我怀疑这样的计算很难在单个 map-reduce 中进行计算,但我不会说这是不可能的。

    【讨论】:

    • 但是统计数据仍然没有给我平均水平。我终于可以使用列表得到我想要的东西了。稍后发布答案。
    【解决方案2】:

    这是我拥有的文档。你会看到我每次有 2 个文档(第二个键)

    {"id":"server_host177.lss.emc.com_2014-05-15_11:39:48","key":["SRMSuite_3.0.2_test1","2014-05-14 11:00:00"],"value":20},
    {"id":"server_host180.lss.emc.com_2014-05-15_11:39:48","key":["SRMSuite_3.0.2_test1","2014-05-14 11:00:00"],"value":20},
    {"id":"server_host090.lss.emc.com_2014-05-15_11:39:55","key":["SRMSuite_3.0.2_test1","2014-05-14 12:00:00"],"value":22},
    {"id":"server_host091.lss.emc.com_2014-05-15_11:39:55","key":["SRMSuite_3.0.2_test1","2014-05-14 12:00:00"],"value":20},
    {"id":"server_host177.lss.emc.com_2014-05-15_11:39:48","key":["SRMSuite_3.0.2_test1","2014-05-14 13:00:00"],"value":26},
    {"id":"server_host180.lss.emc.com_2014-05-15_11:39:48","key":["SRMSuite_3.0.2_test1","2014-05-14 13:00:00"],"value":20},
    {"id":"server_host090.lss.emc.com_2014-05-15_11:39:55","key":["SRMSuite_3.0.2_test1","2014-05-14 14:00:00"],"value":22},
    {"id":"server_host091.lss.emc.com_2014-05-15_11:39:55","key":["SRMSuite_3.0.2_test1","2014-05-14 14:00:00"],"value":20}
    

    我想获得每次的平均值。 这是我的reduce函数:

    "maxcpu": {
             "map": "function(doc) { if ((doc.type == 'performance_stats'))  emit([doc.test_id, doc.start_time], doc.CPU) }",
             "reduce": "function(keys, values) "
                       "{ "
                                "avg = Math.round(sum(values)/values.length);"
                                "return(avg)"
                       " }"
                }
    

    所以,你将有 4 行:

    http:yourhostip:5984/longevity/_design/perfstats/_view/maxcpu?group=true
    
    {"rows":[
    {"key":["SRMSuite_3.0.2_test1","2014-05-14 11:00:00"],"value":20},
    {"key":["SRMSuite_3.0.2_test1","2014-05-14 12:00:00"],"value":21},
    {"key":["SRMSuite_3.0.2_test1","2014-05-14 13:00:00"],"value":23},
    {"key":["SRMSuite_3.0.2_test1","2014-05-14 14:00:00"],"value":21}}
    

    现在要报告最大值 23,我们需要使用列表函数。来自-http://geekiriki.blogspot.com/2010/08/couchdb-using-list-functions-to-sort.html

        "lists":{
            "sort":"function(head, req) {"
                    "var row;"
                    "var rows=[];"
                    "while(row = getRow()) {"
                        "rows.push(row)"
                    "};"
                    "rows.sort(function(a,b) {"
                    "return b.value-a.value"
                    "});"
                    "send(JSON.stringify({\"rows\" : rows[0]}))"
            "}"
    

    那么这会给你你所需要的-

     http://yourhostip:5984/longevity/_design/perfstats/_list/sort/maxcpu?group=true
    
    {"rows":{"key":["SRMSuite_3.0.2_test1","2014-05-14 13:00:00"],"value":87}}
    

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 2021-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多