map / reduce是否适合查找许多记录的一组值的中位数和模式?

时间:2012-01-02 23:02:15

标签: mongodb mapreduce

我在Mongodb中有一组对象,每个对象都嵌入了一组值,例如:

[1.22, 12.87, 1.24, 1.24, 9.87, 1.24, 87.65] // ... up to about 150 values

是地图/减少了在嵌入式阵列中查找中位数(平均值)和模式(最常见值)的最佳解决方案吗?我问的原因是map和reduce都必须返回相同的(结构上)值集。看起来在我的情况下我想要接受一组值(数组)并返回一组两个值(中位数,模式)。

如果没有,最好的方法是什么?我想让它在rake任务中运行,如果那是相关的。这是一个过夜数据处理的事情。

3 个答案:

答案 0 :(得分:0)

这里有关于预期产出的关键问题。你的问题并不是100%清楚你想要的。

你想要(A)

{ _id: "document1", value: { mode: 1.0, median: 10.0 } }
{ _id: "document2", value: { mode: 5.0, median: 150.0 } }
... one for each document

...或者你想要(B),所有阵列的所有组合的模式和中位数。

  • 如果答案是(A),则地图/缩小将有效
  • 如果答案是(B),那么Map / Reduce 可能无效

如果您打算(A),请仔细阅读M / R文档并了解其局限性。选项(A) 可以成为Map / Reduce,它也可以是一个大for循环,其中“{1}}为”{摘要“收集甚至回到原来的收藏品。这可能更有效率。

答案 1 :(得分:0)

我首先阅读此http://www.mongovue.com/2010/11/03/yet-another-mongodb-map-reduce-tutorial/

我想你想要

  1. 用于生成密钥和单个数据元素的地图阶段,
  2. 将所有数据元素放入的缩减阶段 每个键的数据数组
  3. 执行平均值,中位数和模式的最终阶段 对整个集合的操作。


  4.   

    完成功能

         

    可以在缩小后运行finalize函数。   这样的函数是可选的,对于许多map / reduce来说不是必需的   案例。 finalize函数接受一个键和一个值,然后返回一个   最终价值。

         

    function finalize(key, value) -> final_value

         

    您的 reduce 功能可能会   为同一个对象多次调用 使用finalize时   事情最后应该只做一次;例如   计算平均值。

    取自http://www.mongodb.org/display/DOCS/MapReduce

答案 2 :(得分:-4)

我假设你想找到模式&每个文档的中位数,你可以用map reduce来做到这一点。在这种情况下,您计算中位数和& map函数中的mode和reduce将返回未触及的地图结果

map = function() {
   var res = 0;
   for (i = 0; i < this.marks.length; i++) {
      res = res + this.marks[i];
   }
   var median = res/this.marks.length;
   emit(this._id,{marks:this.marks,median:median});
}


reduce = function (k, values) {
    values.forEach(function(value) {
      result = value;
    });
    return result;
}

和本集合

{ "_id" : ObjectId("4f02be1f1ae045175f0eb9f1"), "name" : "ram", "marks" : [ 1.22, 12.87, 1.24, 1.24, 9.87, 1.24, 87.65 ] }
{ "_id" : ObjectId("4f02be371ae045175f0eb9f2"), "name" : "sam", "marks" : [ 1.32, 11.87, 12.4, 4.24, 9.37, 3.24, 7.65 ] }
{ "_id" : ObjectId("4f02be4c1ae045175f0eb9f3"), "name" : "pam", "marks" : [ 3.32, 10.17, 11.4, 2.24, 2.37, 3.24, 30.65 ] }

你可以通过

获得中位数
  db.test.mapReduce(map,reduce,{out: { inline : 1}})

{
    "results" : [
        {
            "_id" : ObjectId("4f02be1f1ae045175f0eb9f1"),
            "value" : {
                "marks" : [
                    1.22,
                    12.87,
                    1.24,
                    1.24,
                    9.87,
                    1.24,
                    87.65
                ],
                "median" : 16.475714285714286
            }
        },
        {
            "_id" : ObjectId("4f02be371ae045175f0eb9f2"),
            "value" : {
                "marks" : [
                    1.32,
                    11.87,
                    12.4,
                    4.24,
                    9.37,
                    3.24,
                    7.65
                ],
                "median" : 7.155714285714285
            }
        },
        {
            "_id" : ObjectId("4f02be4c1ae045175f0eb9f3"),
            "value" : {
                "marks" : [
                    3.32,
                    10.17,
                    11.4,
                    2.24,
                    2.37,
                    3.24,
                    30.65
                ],
                "median" : 9.055714285714286
            }
        }
    ],
    "timeMillis" : 1,
    "counts" : {
        "input" : 3,
        "emit" : 3,
        "reduce" : 0,
        "output" : 3
    },
    "ok" : 1,
}