MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB mappa/riduci su più raccolte?

Una funzione di riduzione può essere chiamata una volta, con una chiave e tutti i valori corrispondenti (ma solo se ci sono più valori per la chiave - non verrà chiamata affatto se c'è solo 1 valore per la chiave).

Può anche essere chiamato più volte, ogni volta con una chiave e solo un sottoinsieme dei valori corrispondenti e il precedente riduce i risultati per quella chiave. Questo scenario è chiamato riduzione . Per supportare le riduzioni, la tua funzione di riduzione dovrebbe essere idempotente.

Ci sono due caratteristiche chiave in una funzione di riduzione idempotente:

  • Il valore di ritorno della funzione di riduzione dovrebbe essere nello stesso formato dei valori prende in. Quindi, se la tua funzione reduce accetta un array di stringhe, la funzione dovrebbe restituire una stringa. Se accetta oggetti con diverse proprietà, dovrebbe restituire un oggetto contenente le stesse proprietà. Ciò garantisce che la funzione non si interrompa quando viene chiamata con il risultato di una precedente riduzione.
  • Non fare supposizioni basate sul numero di valori accetta. Non è garantito che i values il parametro contiene tutto i valori per la chiave data. Quindi usando values.length nei calcoli è molto rischioso e dovrebbe essere evitato.

Aggiornamento: I due passaggi seguenti non sono richiesti (o addirittura possibili, non ho verificato) sulle versioni più recenti di MongoDB. Ora può gestire questi passaggi per te, se specifichi una raccolta di output nelle opzioni di riduzione della mappa:

{ out: { reduce: "tempResult" } }

Se la tua funzione di riduzione è idempotente, non dovresti avere problemi a ridurre più raccolte di mappe. Riduci semplicemente i risultati di ogni raccolta:

Fase 1

Esegui la riduzione della mappa su ogni raccolta richiesta e salva i risultati in un'unica raccolta temporanea. Puoi memorizzare i risultati utilizzando una funzione di finalizzazione:

finalize = function (key, value) {
  db.tempResult.save({ _id: key, value: value });
}

db.someCollection.mapReduce(map, reduce, { finalize: finalize })
db.anotherCollection.mapReduce(map, reduce, { finalize: finalize })

Fase 2

Esegui un'altra riduzione della mappa sulla raccolta temporanea, utilizzando la stessa funzione di riduzione . La funzione mappa è una semplice funzione che seleziona le chiavi e i valori dalla collezione temporanea:

map = function () {
  emit(this._id, this.value);
}

db.tempResult.mapReduce(map, reduce)

Questa seconda riduzione della mappa è fondamentalmente una riduzione e dovrebbe darti i risultati di cui hai bisogno.