MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB über mehrere Sammlungen abbilden/reduzieren?

Eine Reduce-Funktion kann einmal mit einem Schlüssel und allen zugehörigen Werten aufgerufen werden (Aber nur, wenn es mehrere Werte für den Schlüssel gibt - es wird überhaupt nicht aufgerufen, wenn es nur 1 Wert für den Schlüssel gibt).

Es kann auch mehrfach aufgerufen werden, jedes Mal mit einem Schlüssel und nur einer Teilmenge der entsprechenden Werte , und die vorherigen Reduce-Ergebnisse für diesen Schlüssel. Dieses Szenario wird als Re-Reduce bezeichnet . Um Re-Reduces zu unterstützen, sollte Ihre Reduce-Funktion idempotent sein.

Es gibt zwei Hauptmerkmale in einer idempotenten Reduktionsfunktion:

  • Der Rückgabewert der Reduce-Funktion sollten im gleichen Format wie die Werte vorliegen es nimmt auf. Wenn also Ihre Reduce-Funktion ein Array von Strings akzeptiert, sollte die Funktion einen String zurückgeben. Wenn es Objekte mit mehreren Eigenschaften akzeptiert, sollte es ein Objekt zurückgeben, das dieselben Eigenschaften enthält. Dadurch wird sichergestellt, dass die Funktion nicht abbricht, wenn sie mit dem Ergebnis einer vorherigen Reduzierung aufgerufen wird.
  • Machen Sie keine Annahmen basierend auf der Anzahl der Werte es nimmt auf. Es ist nicht garantiert, dass die values Parameter enthält all die Werte für den angegebenen Schlüssel. Verwenden Sie also values.length in Berechnungen ist sehr riskant und sollte vermieden werden.

Aktualisierung: Die beiden folgenden Schritte sind in den neueren MongoDB-Versionen nicht erforderlich (oder sogar möglich, ich habe es nicht überprüft). Es kann diese Schritte jetzt für Sie erledigen, wenn Sie eine Ausgabesammlung in den Map-Reduce-Optionen angeben:

{ out: { reduce: "tempResult" } }

Wenn Ihre Reduce-Funktion idempotent ist, sollten Sie keine Probleme haben, mehrere Sammlungen zu reduzieren. Reduzieren Sie einfach die Ergebnisse jeder Sammlung erneut:

Schritt 1

Führen Sie map-reduce für jede erforderliche Sammlung aus und speichern Sie die Ergebnisse in einer einzigen, temporären Sammlung. Sie können die Ergebnisse mit einer Finalize-Funktion speichern:

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 })

Schritt 2

Führen Sie eine weitere Kartenreduzierung für die temporäre Sammlung durch, unter Verwendung derselben Reduzierungsfunktion . Die Kartenfunktion ist eine einfache Funktion, die die Schlüssel und Werte aus der temporären Sammlung auswählt:

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

db.tempResult.mapReduce(map, reduce)

Diese zweite Kartenreduzierung ist im Grunde eine erneute Reduzierung und sollte Ihnen die gewünschten Ergebnisse liefern.