MongoDB (已解决) 一个 map reduce 的脚本,求和以及求平均值,但是却得到一堆 undefined

ryan · 2013年08月18日 · 最后由 Ryan 回复于 2013年08月19日 · 8879 次阅读

已解决

原来 map reduce 中的 map function 和 reduce function 所返回的结构中的属性名都必须一样。好坑爹啊。。。

    key=this.name;
    value={
        count:1,
        salary:this.salary
    };
    emit(key,value);


reduce_val={count:0,salary:0}; //属性名必须和map的emit中一样

文档格式是这样的:

{
    "_id" : ObjectId("52108dddd81bee8dfd61228b"),
    "name" : "Jobs",
    "birth" : ISODate("2001-03-04T09:03:25Z"),
    "likes" : [],
    "skills" : [ 
        {
            "codeLanguage" : "Ruby",
            "level" : 3
        }
    ],
    "address" : {
        "city" : "D.C",
        "zipCode" : 29607
    },
    "salary" : 2107
}
//map func
var map_func=function(){
    key=this.name;
    value={
        count:1,
        salary:this.salary
    };
    emit(key,value);
}

//reduce func
var reduce_func=function(key,value){
    reduce_val={count:0,total_salary:0};
    print(value[0].count+"and"+value[0].salary);
    for (var i = 0; i<value.length; i++) {
        reduce_val.count+=value[i].count;
        reduce_val.total_salary+=parseInt(value[i].salary);
    };

    return reduce_val;
}

var finalize_func=function(key,reduce_val){
    reduce_val.avg=reduce_val.total_salary/reduce_val.count;
    return reduce_val;
}

db.pixel.mapReduce(
        map_func,
        reduce_func,
        {
            out:"map_reduce_avg",
            query:{
                "skills.1":{$exists:1}
            },
            finalize:finalize_func
        }
    )

我通过print()函数发现,reduce 函数中的value[0].salary只有前 6 次是有值的,之后就全部变成了undefined的了。。。而这个 6 次又正好和 key 的个数相同。。。我想他们之间一定有联系,只是不明白,为什么第七次开始的 reduce 就全部undefined了呢。

1and3222
1and3303
1and2376
1and2721
1and2958
1and3280
16andundefined
13andundefined
21andundefined

文档格式是 json 吗? 直接

require 'json'
obj = JSON.parse open('doc.txt').read
p obj

#1 楼 @sevk 不是,不是用 ruby,都是直接在 shell 里面操作,这个文档格式只是展示一下,数据库里面一个文档有哪些字段而已。关键是 map reduce。你这个已经答非所问了。。。。

Reduce 的结果会被作会 reduce 的输入,直到 reduce 成一个。要不然后不就只能顺序执行了么。

The reduce function must return an object whose type must be identical to the type of the value emitted by the map function. -- Troubleshoot the Reduce Function

#3 楼 @doitian 就是要和 map 出来的数据类型一样么。reduce_val={count:0,total_salary:0}; 那我这个也没错啊。和 map 出来的不是一样的么。

#4 楼 @Ryan 要和 emit 结果一样

#5 楼 @doitian reduce_val={count:0,total_salary:0}; value={ count:1, salary:this.salary }; emit(key,value);

这不是和 emit 中的 value 结果一样么。。。。

#5 楼 @doitian 解决了。。。。只要reduce_val={count:0,total_salary:0};改成reduce_val={count:0,salary:0};就可以了,连属性名字都必须是一样的。。卧槽,好坑爹。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号