2012-06-13 6 views
18

Quindi io sono nuovo con MongoDB e MapReduce in generale e mi sono imbattuto in questo "capriccio" (o almeno nella mia mente un capriccio)MongoDB MapReduce - emettere una chiave/valore di uno pretende molto chiamare ridurre

Dire che ho oggetti nella mia collezione in questo modo:

{ 'chiave': 5, 'valore': 5}

{ 'chiave': 5, 'valore': 4}

'chiave' { : 5, 'valore': 1}

{ 'chiave': 4, 'valore': 6}

{ 'chiave': 4, 'valore': 4}

{ 'chiave': 3, 'valore': 0}

mio mappa funzione emette semplicemente la chiave e il valore

mio ridurre funzione aggiunge semplicemente i valori e prima di tornare li aggiunge 1 (ho fatto questo per controllare per vedere se la funzione di ridurre è e ven chiamato)

miei risultati seguono:

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

{ '_id': 4, 'valore': 11.0}

{ '_id': 5, 'valore': 11.0}

Come si può vedere, per i tasti 4 & 5 ottengo la risposta attesa di 11, ma per ° e tasto 3 (con una sola voce nella collezione con quella chiave) ottengo l'inaspettato 0!

È questo comportamento naturale di mapreduce in generale? Per MongoDB? Per il pymongo (che sto usando)?

risposta

34

La funzione di riduzione combina i documenti con la stessa chiave in un unico documento. Se la funzione mappa emette un singolo documento per un particolare tasto (come nel caso del tasto 3), la funzione di riduzione non verrà chiamata.

+9

Giusto per essere chiari, questo è il modo in cui è stata progettata la riduzione della mappa. Se desideri modificare i documenti con chiavi univoche (come la chiave 3), considera l'utilizzo della funzione finalize: http://www.mongodb.org/display/DOCS/MapReduce#MapReduce-FinalizeFunction – Jenna

+3

qual è la soluzione se vogliamo includere chiave con singolo documento nei risultati ??? –

+1

@RaviKhakhkhar i singoli documenti sono ancora inclusi nei risultati, solo le funzioni di riduzione non vengono mai chiamati su di loro – Cilvic

0

È questo comportamento naturale di mapreduce in generale?

Sì.

+9

No - questo non è naturale per "MR in generale". Né la carta MR originale né la mappa Hadoop riducono. Potresti voler convertire quel "1" in un altro tipo nel riduttore, giusto? Quindi in generale saltare il riduttore sarebbe un'idea piuttosto brutta/bizzarra ;-) Questo non significa che il MR di mongo non lo faccia, ma non è "il comportamento atteso _in generale_". –

+0

Qui http://docs.mongodb.org/manual/tutorial/troubleshoot-reduce-function/ Mongo dice che retuce deve restituire il valore dello stesso tipo di mappa. Tuttavia, sono d'accordo che è cattivo, bizzarro, inaspettato e poco chiaro. – amorfis

4

Mi rendo conto che è una domanda più vecchio, ma mi è venuto ad esso e sentivo come se ancora non ho capito perché questo comportamento esiste e come costruire la mappa/ridurre la funzionalità quindi è un non-problema.

Il motivo per cui MongoDB non chiama la funzione di riduzione se c'è una singola istanza di una chiave è perché non è necessario (spero che questo abbia più senso in un momento). I seguenti sono requirements for reduce functions:

  • la funzione di ridurre deve restituire un oggetto il cui tipo deve essere identica al tipo del valore emessa dalla funzione carta.
  • L'ordine degli elementi nel valoriArray non deve influire sull'output della funzione di riduzione
  • La funzione di riduzione deve essere idempotente.

Il primo requisito è molto importante e mi sembra un numero di persone si affacciano perché ho visto un numero di persone mappatura nella funzione di ridurre quindi trattare il caso solo tasto nella funzione di finalizzazione . Questo è il modo sbagliato per risolvere il problema, tuttavia.

Pensate in questo modo: Se c'è solo una singola istanza di una chiave, una semplice ottimizzazione è di saltare completamente il riduttore (non c'è nulla da ridurre). I valori a chiave singola sono ancora inclusi nell'output, ma l'intento del riduttore è quello di creare un risultato aggregato dei documenti a più chiavi nella raccolta. Se il mappatore e il riduttore stanno emettendo lo stesso tipo, si dovrebbe essere beatamente inconsapevoli guardando la struttura dell'oggetto dell'output dalla mappa/riduci le funzioni. Non è necessario utilizzare una funzione finalizzata per correggere la struttura degli oggetti che non sono stati eseguiti attraverso il riduttore.

In breve, eseguire la mappatura nella funzione della mappa e ridurre i valori multi-chiave in un unico risultato aggregato nelle funzioni di riduzione.

3

Soluzione:

  • aggiunto un nuovo campo in mappa: singola: 0
  • in ridurre cambiamento questo campo per: singola: 1
  • in finalizzare rendono il controllo di questo campo ed effettuare azioni richieste

    $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; 
    };"); 
    
Problemi correlati