MongoDB MapReduce: Nie działa zgodnie z oczekiwaniami dla ponad 1000 rekordów
Napisałem funkcję mapreduce, w której rekordy są emitowane w następującym formacie
{userid:<xyz>, {event:adduser, count:1}}
{userid:<xyz>, {event:login, count:1}}
{userid:<xyz>, {event:login, count:1}}
{userid:<abc>, {event:adduser, count:1}}
gdzie userid jest kluczem, a pozostałe to wartość tego klucza. Po funkcji MapReduce chcę uzyskać wynik w następującym formacie
{userid:<xyz>,{events: [{adduser:1},{login:2}], allEventCount:3}}
Aby to osiągnąć, napisałem następującą funkcję redukcyjną, którą wiem, że można to osiągnąć przez grupę zarówno w strukturze agregacji, jak i mapreduce, ale potrzebujemy podobnej funkcjonalności dla złożonego scenariusza. Tak więc przyjmuję to podejście.
var reducefn = function(key,values){
var result = {allEventCount:0, events:[]};
values.forEach(function(value){
var notfound=true;
for(var n = 0; n < result.events.length; n++){
eventObj = result.events[n];
for(ev in eventObj){
if(ev==value.event){
result.events[n][ev] += value.allEventCount;
notfound=false;
break;
}
}
}
if(notfound==true){
var newEvent={}
newEvent[value.event]=1;
result.events.push(newEvent);
}
result.allEventCount += value.allEventCount;
});
return result;
}
Działa to doskonale, gdy uruchamiam 1000 rekordów, gdy są rekordy 3k lub 10k, otrzymuję wynik podobny do tego
{ "_id" : {...}, "value" :{"allEventCount" :30, "events" :[ { "undefined" : 1},
{"adduser" : 1 }, {"remove" : 3 }, {"training" : 1 }, {"adminlogin" : 1 },
{"downgrade" : 2 } ]} }
Nie jestem w stanie zrozumieć, gdzie to jestundefined
pochodzi, a suma poszczególnych zdarzeń jest mniejsza niż allEventCount. Wszystkie dokumenty w kolekcji mają niepuste poleevent
więc nie ma szans na niezdefiniowanie.
Wersja Mongo DB - 2.2.1 Środowisko - Komputer lokalny, bez shardingu.
W funkcji redukcji, dlaczego ta operacja nie powiedzie sięresult.events[n][ev] += value.allEventCount;
kiedy podobna operacjaresult.allEventCount += value.allEventCount;
Karnety?
Poprawiona odpowiedź sugerowana przez JohnaHK
Zmniejsz funkcję:
var reducefn = function(key,values){
var result = {totEvents:0, event:[]};
values.forEach(function(value){
value.event.forEach(function(eventElem){
var notfound=true;
for(var n = 0; n < result.event.length; n++){
eventObj = result.event[n];
for(ev in eventObj){
for(evv in eventElem){
if(ev==evv){
result.event[n][ev] += eventElem[evv];
notfound=false;
break;
}
}}
}
if(notfound==true){
result.event.push(eventElem);
}
});
result.totEvents += value.totEvents;
});
return result;
}