我在collecton中有1000个用户记录,其中459个文档有性别男性,其余为女性
//document structure
> db.user_details.find().pretty()
{
"_id" : ObjectId("557e610d626754910f0974a4"),
"id" : 0,
"name" : "Leanne Flinn",
"email" : "leanne.flinn@unilogic.com",
"work" : "Unilogic",
"dob" : "Fri Jun 11 1965 20:50:58 GMT+0530 (IST)",
"age" : 5,
"gender" : "female",
"salary" : 35696,
"hobbies" : "Acrobatics,Meditation,Music"
}
{
"_id" : ObjectId("557e610d626754910f0974a5"),
"id" : 1,
"name" : "Edward Young",
"email" : "edward.young@solexis.com",
"work" : "Solexis",
"dob" : "Wed Feb 12 1941 16:45:53 GMT+0530 (IST)",
"age" : 1,
"gender" : "female",
"salary" : 72291,
"hobbies" : "Acrobatics,Meditation,Music"
}
{
"_id" : ObjectId("557e610d626754910f0974a6"),
"id" : 2,
"name" : "Haydee Milligan",
"email" : "haydee.milligan@dalserve.com",
"work" : "Dalserve",
"dob" : "Tue Sep 13 1994 13:45:04 GMT+0530 (IST)",
"age" : 17,
"gender" : "male",
"salary" : 20026,
"hobbies" : "Papier-Mache"
}
{
"_id" : ObjectId("557e610d626754910f0974a7"),
"id" : 3,
"name" : "Lyle Keesee",
"email" : "lyle.keesee@terrasys.com",
"work" : "Terrasys",
"dob" : "Tue Apr 25 1922 13:39:46 GMT+0530 (IST)",
"age" : 79,
"gender" : "female",
"salary" : 48032,
"hobbies" : "Acrobatics,Meditation,Music"
}
{
"_id" : ObjectId("557e610d626754910f0974a8"),
"id" : 4,
"name" : "Shea Mercer",
"email" : "shea.mercer@pancast.com",
"work" : "Pancast",
"dob" : "Mon Apr 08 1935 06:10:30 GMT+0530 (IST)",
"age" : 51,
"gender" : "male",
"salary" : 31511,
"hobbies" : "Acrobatics,Photography,Papier-Mache"
}
每个性别的用户数
> db.user_details.find({gender:'male'}).count()
459
>
> db.user_details.find({gender:'female'}).count()
541
> db.user_details.find({name:{$ne:null}}).count()
1000
> db.user_details.find({age:{$ne:null}}).count()
1000
地图缩减代码
mapper = function(){
emit(this.gender, {name:this.name,age:this.age})
}
reducer = function(gender, users){
var res = 0;
users.forEach(function(user){
res = res + 1
})
return res;
}
db.user_details.mapReduce(mapper, reducer, {out: {inline:1}})
为什么map reduce结果只有112个文件?男性和女性应分别包含459和541,不是吗?
// Map reduce result
{
"results" : [
{
"_id" : "female",
"value" : 56
},
{
"_id" : "male",
"value" : 46
}
],
"timeMillis" : 45,
"counts" : {
"input" : 1000,
"emit" : 1000,
"reduce" : 20,
"output" : 2
},
"ok" : 1
}
注意:我知道这不是使用map reduce的正确方法,实际上我在map reduce中面临一些更令人毛骨悚然的问题。一旦我得到这个问题的解决方案,我就可以解决这个问题
答案 0 :(得分:1)
你的问题在于你错过了mapReduce如何工作的核心概念之一。找到解释此问题的相关文档here:
- MongoDB可以为同一个密钥多次调用reduce函数。在这种情况下,该键的reduce函数的先前输出将成为该键的下一个reduce函数调用的输入值之一。
然后又过了一会儿:
- 返回对象的类型必须与map函数
发出的值的类型相同
这两个陈述的含义是您需要使用映射器和 reducer 函数发出的完全相同签名作为<强>减少过程确实会被多次调用#34;。
这就是mapReduce处理大数据的方式,但不一定要为给定的&#34;键&#34;处理所有相同的值。立刻,但在增量&#34;块&#34;:
如果输出中你想要的只是一个&#34;数字&#34;然后你所有&#34;发出&#34;只是一个&#34;数字&#34;以及:
db.collection.mapReduce(
function() {
emit(this.gender, this.age);
},
function(key,values) {
return Array.sum( values )
},
{ "out": { "inline": 1 } }
)
或者只是&#34;计算&#34;每种类型:
db.collection.mapReduce(
function() {
emit(this.gender, 1);
},
function(key,values) {
return Array.sum( values )
},
{ "out": { "inline": 1 } }
)
关键是&#34;你需要把你输入的内容和#34;放在一起,因为它很可能会再次回到&#34;。因此,无论您要收集哪些数据,mapper和reducer 的输出结构必须相同。
答案 1 :(得分:0)
这可能是错误的。
users.forEach(function(user){
res = res + 1
})
试试这个,
function(gender, users){
return Array.sum( users)
}
答案 2 :(得分:0)
减少功能有误。
MONGODB reduce函数可以为同一个KEY多次调用,因此在你的reduce代码中它被覆盖。
同样在map函数中,您正在发出结构{user,age}的文档,但在reduce函数中,您将返回计数。
reduce = function(gender, doc) {
reducedVal = { user: 0, age: 0 };
for (var idx = 0; idx < doc.length; idx++) {
reducedVal.user += 1 ;
reducedVal.age += 1;
}
return reducedVal;
};
请查看以下链接:
http://thejackalofjavascript.com/mapreduce-in-mongodb/
答案 3 :(得分:0)
这是使用地图reduce()的正确方法,用于按性别显示用户数
db.yourCollectionName.mapReduce(
function(){
emit(this.gender,1);
},
function(k,v){
return Array.sum(v);
},
{out:"genderCount"}
);
db.genderCount.find();