MongoDB MapReduce发射器

时间:2014-06-04 11:06:41

标签: mongodb mapreduce

我有一个运行在集合上的MapReduce查询 - mycollection - 目前包含4个文档,每个文档都具有相同的结构:

{           
    myobject: {
        key_field: "some_name",
        one_number: 15,
        other_numer: 20
    },
    some_more_data: {}
}

key_field 不是唯一的。在这个例子中,我有4个文件,其中 key_field:“some_name”,总共约400个。

reduce()fumction对 one_number other_number 执行一些算术运算,并且应该将结果输出到新的集合( my_mapreduce_collection ):

var map = function() {
    emit(this.myobject.key_field, {
        field1: this.myobject.one_number, 
        field2: this.myobject.other_number
    });
};

var reduce = function(key, values) {
    var sum = 0;
    values.forEach(function(doc, idx) {

        //Output each iteration:
        print("Key: "+key+", Idx: "+idx+" --> "+JSON.stringify(doc));

        sum += (doc.field1 - doc.field2);
    });
    return sum;
};

var MR = {
  mapreduce: "my_mongodb_collection", 
  out:  "my_mapreduce_collection",
  map: map.toString(),
  reduce: reduce.toString()
};

但是,我有时会在某些 key_field 上获得 nan 值。

所以,我在 reduce()上添加了 print()函数,这就是它输出的内容:

  

...

     

密钥:some_name,Idx:0 - > { “one_number”:15, “other_number”:20}

     

密钥:some_name,Idx:1 - > { “one_number”:10 “other_number”:30}

     

密钥:some_name,Idx:0 - > 0

     

密钥:some_name,Idx:1 - > { “one_number”:20, “other_number”:40}

     

密钥:some_name,Idx:2 - > { “one_number”:25, “other_number”:50}

     

...

由于某种原因,我得到一个值“0”,而不是一个对象,然后索引重新启动。这只发生在一些文件上。我检查了它们,它们看起来都是同质的。

对可能发生的事情有任何想法?

谢谢!

1 个答案:

答案 0 :(得分:1)

您正在错误地使用mapReduce。从reduce返回的值应该与从map中发出的值相同。虽然你这样做的方式看起来似乎有效,但只要你达到100条记录,你就会看到它是如何破坏的。

你的索引再次开始的原因是因为可以多次调用reduce(第二个中的第一个结果),这是我之前评论的来源。这就是为什么你得到0之间的原因,因为形状不匹配。

您应该使用finalize函数对先前减少的值求和。

var map = function() {
    emit(this.myobject.key_field, {
        field1: [this.myobject.one_number], 
        field2: [this.myobject.other_number]
    });
};

var reduce = function(key, values) {
    var res = {
        field1: [], 
        field2: []
    };
    values.forEach(function(doc, idx) {
        res.field1 = res.field1.concat(doc.field1);
        res.field2 = res.field2.concat(doc.field2);
    });
    return res;
};