2011-01-04 13 views
2

ursprüngliche Sammlung:mongodb mapreduce - ein Array oder ein Objekt im Reduce erstellen?

{ 
"_id" : ObjectId('xxxxxxxxxxxxxxxx'), 
    "userId" : ObjectId('yyyyyyyyyyyyyyyy'), 
    "urlId" : ObjectId('zzzzzzzzzzzzzzzzzz') 
}, 
{ 
    "_id" : ObjectId('uuuuuuuuuuuuuuuuuu'), 
    "userId" : ObjectId('aaaaaaaaaaaaaaaa'), 
    "urlId" : ObjectId('zzzzzzzzzzzzzzzzzz') 
} 

emittieren:

emit(this.urlId, {userId: this.userId, visitCount: this.visitCount}); 

reduzieren:

function(key, values) { 
    var visitCount = 0; 
    var userVC = new Array(); 
    values.forEach(function(doc) { 


NOT SURE WHAT TO PUT HERE TO ACHIEVE DESIRED OUTPUT COLLECTION 


    }); 
    return {urlId: key, userVC: userVC}; 
}; 

MR Ausgang Sammlung gewünscht:

{ 
    "_id" : ObjectId('zzzzzzzzzzzzzzzzzzzz'), 
    "value" : { 
     "urlId" : ObjectId('zzzzzzzzzzzzzzzzzzzz'), 
     "userVC" : { 
       ObjectId('yyyyyyyyyyyyyyyy') : <total visit count for this userId on this urlId>, 
       ObjectId('aaaaaaaaaaaaaaaa') : <total visit count for this userId on this urlId> 
     } 
} 

Antwort

3

Sie wollen t o wissen, wie oft jeder Benutzer jede einzelne URL auf Ihrer Website besucht hat? Ich denke, du wirst das anders lösen wollen.

Emit eine Anzahl von URL/user Besuche:

emit({ urlId: this.urlId, userId: this.userId }, { count: 1 }); 

Zähle sie die mit reduzieren:

r = function(key , values){ 
    var total = 0; 
    for (var i=0; i<values.length; i++) 
     total += values[i].count; 
    return { count : total }; 
}; 

Dann, wenn Sie wirklich, wirklich die gewünschte Ausgabe, die Sie angegeben wollten, könnten Sie das tun in ein Abschlussschritt. Aber ich denke, dass es für N Benutzer nicht gut skaliert.

Hier ist ein Link, der nicht genau Ihr erklärtes Ziel nicht erfüllt, aber ich fand, sehr nützlich, wenn man versucht zu verstehen, wie diese mongodb mapreduce Funktionen arbeiten:

http://cookbook.mongodb.org/patterns/unique_items_map_reduce/

+0

Eine zweite Map-Reduce-Operation könnte verwendet werden, um die Sammlung mit einem Schlüssel der Benutzer-AND-URL in eine mit einem Schlüssel für den Benutzer und einen Wert mit dem Array von Zählern umzuwandeln. –

+0

Da Sie eins zuweisen, tun Sie dies für '(var i = 0; i Danielo515

+0

Nicht so @ Danielo515. Wir ordnen die Zählung 1 in der Karte zu, aber die Reduktion kann viele Male in beliebiger Reihenfolge geschehen, wobei emittierte Werte von der Karte mit vorher reduzierten Werten von einer Untermenge gemischt werden. Mit anderen Worten, innerhalb der Reduzierungsfunktion ist der Zählwert nicht immer eins. – Chris

0

Für jemand anderes dieses Problem zu lösen versuchen, in der Funktion reduzieren:

function reduce(key, values) { 
    const result = { 
    list: [], 
    ... 
    }; 

    // keep track of reduced records to avoid duplicate list entries 
    const processed = { 
    list: [], 
    ... 
    }; 

    values.forEach((value, index) => { 
    if (value.listItem && value.listItem.length > 0) { 

     // our value is an array as MongoDB needs to be strongly typed (same as reduced type) 
     if (processed.list.indexOf(value.listItem[0].key) === -1) { 
     result.list = result.list.concat(value.listItem); 
     } 

    } 
    ... 
    }); 

    return result; 
} 

die verringern Funktion im Zusammenhang mit MongoDB läuft, so dass Sie sich bewusst sein müssen, was in der Funktion geht, die unterstützt wird.