mapReduce或嵌套属性平均值的聚合

时间:2014-04-30 21:03:43

标签: mongodb mapreduce aggregation-framework

我的收藏夹中有这样的文件:

- 小时

----分钟

...每小时是一天的财产,每分钟是一小时的财产:

///first hour, first minute ... last hour, last minute
{
 0: {0:{x:1, y:2}...59:{x:3, y:8}}
 ...
 23: {0:{x:1, y:2}...59:{x:3, y:8}} 
}

我想平均分钟属性的值,以返回这样的文档集合:

//first hour, average values ... last hour, average values

{
0:{x:2, y:5}
...
23:{x:2, y:5}
}

我可以使用mapReduce或聚合管道来执行此操作吗?怎么样?

一个问题:我还想过滤掉预先格式化的会议记录,如下所示:

59: {x:0, y:0} // zero means null record 

1 个答案:

答案 0 :(得分:0)

是的,这是没有减速器的mapReduce逻辑。

所以考虑到你的结构有点像这样:

{
    "series": {
        0:  { 0:{x:1, y:2}, 1: { x:0, y:0 }, 59:{x:3, y:8} },
        23: { 0:{x:1, y:2}, 59:{x:3, y:8} } 
    }
}

然后定义一个映射器:

var mapper = function () {

  var output = {};

  for ( h in this.series ) {

    var minutes = {x: 0, y: 0};
    var count = 0;

    for ( m in this.series[h] ) {
      if ( ( this.series[h][m].x != 0 ) &&
           ( this.series[h][m].y != 0 ) )
      {
        minutes.x += this.series[h][m].x;
        minutes.y += this.series[h][m].y;
        count++;
      }
    }

    minutes.x = Math.floor( minutes.x / count );
    minutes.y = Math.floor( minutes.y / count );

    output[h] = minutes;

  }

  emit( this._id, output );

};

然后运行mapReduce:

db.series.mapReduce(mapper,function(){},{ out: { inline: 1 } })

它为您提供输出:

    "results" : [
            {
                    "_id" : ObjectId("53618345e10ce3c73df3ff24"),
                    "value" : {
                            "0" : {
                                    "x" : 2,
                                    "y" : 5
                            },
                            "23" : {
                                    "x" : 2,
                                    "y" : 5
                            }
                    }
            }
    ],

并且每个文档都会这样做。

使用您当前的结构,无法使用聚合框架进行转换,因为所有元素都是子文档,聚合框架无法在不明确命名每个元素的情况下遍历