2012-06-13 5 views
18

Also ich bin neu mit mongodb und mapreduce im Allgemeinen und kam in dieser „Marotte“ (oder zumindest in meinem Kopf eine Marotte)MongoDB MapReduce - Emit einen Schlüssel/Wert eines nennt doesnt reduzieren

Say I-Objekte haben in meiner Sammlung wie folgt:

{ 'key': 5, 'Wert': 5}

{ 'key': 5, 'Wert': 4}

{ 'key' : 5, 'Wert': 1}

{ 'key': 4, 'Wert': 6}

{ 'key': 4, 'Wert': 4}

{ 'Schlüssel': 3, 'Wert': 0}

Meine Karte Funktion sendet einfach den Schlüssel und den Wert

Meine reduzieren Funktion fügt einfach die Werte uND vor der Rückkehr sie addiert 1 (ich habe diese, um zu prüfen, ob die Funktion reduzieren ist e ven genannt)

Meine Ergebnisse folgen:

{ '_id': 3, 'Wert': 0}

{ '_id': 4, 'Wert': 11,0}

{ '_id': 5, 'Wert': 11,0}

Wie Sie sehen können, für die Tasten 4 & 5 I die erwartete Antwort von 11 bekommen, aber für th e Taste 3 (mit nur einem Eintrag in der Sammlung mit diesem Schlüssel) Ich bekomme die unerwartete 0!

Ist das natürliche Verhalten von mapreduce im Allgemeinen? Für MongoDB? Für Pymongo (was ich benutze)?

Antwort

34

Die Reduzierungsfunktion kombiniert Dokumente mit demselben Schlüssel in einem Dokument. Wenn die Kartenfunktion ein einzelnes Dokument für eine bestimmte Taste ausgibt (wie bei Taste 3), wird die Reduzierungsfunktion nicht aufgerufen.

+9

Nur um klar zu sein, dies ist die Art und Weise wie Map Reduce entworfen wurde. Wenn Sie Dokumente mit eindeutigen Schlüsseln (wie Schlüssel 3) modifizieren möchten, sollten Sie die Finalize-Funktion in Betracht ziehen: http://www.mongodb.org/display/DOCS/MapReduce#MapReduce-FinalizeFunction – Jenna

+3

Was ist die Lösung, wenn wir einbeziehen möchten Schlüssel mit Einzeldokument in Ergebnissen ??? –

+1

@RaviKhakhkhar die einzelnen Dokumente sind noch in den Ergebnissen enthalten, nur die Reduce-Funktionen werden nie auf sie – Cilvic

0

Ist das natürliche Verhalten von mapreduce im Allgemeinen?

Ja.

+9

Nein - das ist für "MR im Allgemeinen" nicht selbstverständlich. Weder das Original-MR-Papier noch Hadoop Map Reduce tun dies. Vielleicht möchtest du diese "1" in einen anderen Typ im Reducer umwandeln, richtig? Im Allgemeinen wäre der Reducer also eine ziemlich schlechte/komische Idee ;-) Das bedeutet nicht, dass mongos MR es nicht tut - aber es ist nicht "das erwartete Verhalten _in general_". –

+0

Hier http://docs.mongodb.org/manual/tutorial/troubleshoot-reduce-function/ Mongo sagt, dass die Rückführung einen Wert vom selben Typ zurückgeben muss. Ich stimme jedoch zu, dass es schlecht, komisch, unerwartet und unklar ist. – amorfis

4

Ich weiß, dies ist eine ältere Frage, aber ich kam zu ihm und fühlte, wie ich immer noch nicht verstehen, warum dieses Verhalten existiert und wie Karte bauen/Funktionalität reduzieren, so dass es kein Thema ist.

Der Grund, warum MongoDB die Reduce-Funktion nicht aufruft, wenn es eine einzelne Instanz eines Schlüssels gibt, ist, weil es nicht notwendig ist (ich hoffe, dass das in einem Moment mehr Sinn ergibt). Die folgenden sind requirements for reduce functions:

  • Die Funktion reduzieren muss ein Objekt, dessen Typ zurück identisch auf den Typ des Wertes durch die Kartenfunktion ausgegeben werden müssen.
  • Die Reihenfolge der Elemente im valuesArray sollte die Ausgabe der Reduce-Funktion nicht beeinflussen
  • Die Reduce-Funktion muss idempotent sein.

Die erste Anforderung ist sehr wichtig, und es scheint eine Reihe von Menschen mit Blick auf sie, weil ich eine Reihe von Menschen Abbildung in der Funktion dann mit dem Single-Schlüsselfall in der Finalisierung Funktion zu tun reduzieren gesehen habe . Dies ist jedoch der falsche Weg, um das Problem anzugehen.

Denken Sie darüber nach: Wenn es nur eine einzige Instanz eines Schlüssels gibt, besteht eine einfache Optimierung darin, den Reduzierer ganz zu überspringen (es gibt nichts zu reduzieren). Ein-Schlüssel-Werte sind immer noch in der Ausgabe enthalten, aber die Absicht des Reduzierers ist es, ein aggregiertes Ergebnis der Mehrfach-Schlüssel-Dokumente in Ihrer Sammlung zu erstellen. Wenn der Mapper und der Reducer den gleichen Typ ausgeben, sollten Sie sich die Objektstruktur der Ausgabe Ihrer map/reduce-Funktionen glücklicherweise nicht merken. Sie sollten keine Finalize-Funktion verwenden müssen, um die Struktur Ihrer Objekte zu korrigieren, die nicht durch den Reducer verlaufen.

Kurz gesagt, machen Sie Ihr Mapping in Ihrer Kartenfunktion und reduzieren Sie Multi-Key-Werte in ein einziges, aggregiertes Ergebnis in Ihren Reduce-Funktionen.

3

Lösung:

  • hinzugefügt neues Feld in Karte: single: 0
  • in reduzieren Änderung dieses Feld auf: single: 1
  • in finalisieren machen für diese Prüfung Feld und erforderliche Aktionen vornehmen

    $map = new MongoCode("function() { 
        var value = { 
         time: this.time, 
         email_id: this.email_id, 
         single: 0 
        }; 
    
        emit(this.email, value); 
    }"); 
    
    $reduce = new MongoCode("function(k, vals) { 
    
        // make some need actions here 
        return { 
         time: vals[0].time, 
         email_id: vals[0].email_id, 
         single: 1 
        }; 
    }"); 
    
    $finalize = new MongoCode("function(key, reducedVal) { 
        if (reducedVal.single == 0) { 
         reducedVal.time = 11111; 
        } 
        return reducedVal; 
    };"); 
    
Verwandte Themen