我正在尝试在我们的应用中聚合一堆用户个人资料数据。每个用户都有一个嵌入的个人资料文档,其中包含性别和种族属性。
{
'email': 'foo@email.com',
'profile': {
'gender': 'male',
'ethnicity': 'Hispanic'
}
}
如果我使用这样的群组功能:
db.respondents.group({
key: {},
initial: {'gender': {'male':0,'female':0}, 'ethnicity': {}, 'count': 0},
reduce: function (user, totals) {
var profile = user.profile;
totals.gender[profile.gender]++;
totals.ethnicity[profile.ethnicity] = (totals.ethnicity[profile.ethnicity] || 0);
totals.ethnicity[profile.ethnicity]++
totals.count++;
}
});
我以我想要的形式得到结果:
{
"gender" : {
"male" : ###,
"female" : ###
},
"ethnicity" : {
"Caucasian/White" : ###,
"Hispanic" : ###,
...
},
"count" : ###
}
我无法将其作为map / reduce命令使用,当然使用不同的reduce函数。我不确定如何将总数加起来。它们总是不正确的。我知道我的reduce输出必须与map中的输入格式相同,但我觉得我错过了减少工作方式的东西......
作为对@Jenna的回应,输入如下:
{
'email': 'foo@email.com',
'profile': {
'gender': 'male',
'ethnicity': 'Hispanic'
}
}
,功能是:
function map(){
emit('demographics', this.profile)
}
function reduce (key, values) {
var reduced = {'gender': {'male':0,'female':0}, 'ethnicity': {}, 'count': 0};
values.forEach(function(value) {
reduced.gender[value.gender]++;
reduced['ethnicity'][value.ethnicity] = (reduced['ethnicity'][value.ethnicity] || 0);
reduced['ethnicity'][value.ethnicity]++;
reduced.count++;
});
return reduced;
}
,输出为:
{
"_id": "demographics",
"value": {
"gender": {
"male": 76.0,
"female": 64.0
},
"ethnicity": {
"Caucasian/White": 109.0,
"Other": 5.0,
"Asian": 10.0,
"African-American": 8.0,
"Hispanic": 7.0,
"Native American": 1.0
},
"count": 141.0
}
}
输出方式不正确,因为数据库中有超过100k的记录。
答案 0 :(得分:2)
可以在先前调用的输出上再次调用reduce函数。你是正确的,map的输出应该与reduce的输出相同。您当前的map函数返回的内容与reduce函数不同。尝试这样的事情:
function map(){
result = {'gender': {'male': 0, 'female': 0}, 'ethnicity': {}, 'count': 1};
result['gender'][this.gender] = 1;
result['ethnicity'][this.ethnicity] = 1;
emit('demographics', result);
}
function reduce (key, values) {
var reduced = {'gender': {'male':0,'female':0}, 'ethnicity': {}, 'count': 0};
values.forEach(function(value) {
reduced['gender']['male'] += value['gender']['male'];
reduced['gender']['female'] += value['gender']['female'];
for(ethnicity in value['ethnicity']){
if(reduced['ethnicity'][ethnicity] === undefined)
reduced['ethnicity'][ethnicity] = 0
reduced['ethnicity'][ethnicity] += value['ethnicity'][ethnicity]
}
reduced['count'] += values.count;
});
return reduced;
}