MongoDB Map Reduce
Map-Reduce ist ein Berechnungsmodell. Einfach ausgedrückt zerlegt es große Arbeitsmengen (Daten) in kleinere Aufgaben (MAP) zur Ausführung und führt dann die Ergebnisse zum Endergebnis (REDUCE) zusammen.
Das Map-Reduce von MongoDB ist sehr flexibel und für die Datenanalyse im großen Maßstab recht praktisch.
MapReduce-Befehle
Nachfolgend finden Sie die grundlegende Syntax von MapReduce:
>db.collection.mapReduce(
function() {emit(key,value);}, //map 函数
function(key,values) {return reduceFunction}, //reduce 函数
{
out: collection,
query: document,
sort: document,
limit: number
}
)
Um MapReduce zu verwenden, müssen Sie zwei Funktionen implementieren: die Map-Funktion und die Reduce-Funktion. Die Map-Funktion ruft emit(key, value) auf, durchläuft alle Datensätze in der Collection und übergibt den Schlüssel und den Wert an die Reduce-Funktion zur Verarbeitung.
Die Map-Funktion muss emit(key, value) aufrufen, um Schlüssel-Wert-Paare zurückzugeben.
Parameter description:
- map: Mapping-Funktion (erzeugt eine Folge von Schlüssel-Wert-Paaren, die als Parameter der reduce-Funktion verwendet wird).
- reduceReduce-Funktion. Die Aufgabe der Reduce-Funktion besteht darin, Key-Values in Key-Value umzuwandeln, das heißt, das Werte-Array in einen einzelnen Wert umzuwandeln.
- outDie Collection, in der die statistischen Ergebnisse gespeichert werden (wenn nicht angegeben, wird eine temporäre Collection verwendet, die automatisch gelöscht wird, nachdem die Client-Verbindung getrennt wurde).
- queryEine Filterbedingung; nur Dokumente, die die Bedingung erfüllen, rufen die Map-Funktion auf. (query, limit, sort können frei kombiniert werden)
- sortDer Sort-Parameter in Kombination mit limit (sortiert Dokumente auch, bevor sie an die Map-Funktion gesendet werden), was den Gruppierungsmechanismus optimieren kann
- limitDie Obergrenze für die Anzahl der an die Map-Funktion gesendeten Dokumente (ohne limit ist die alleinige Verwendung von sort nicht sehr nützlich)
Das folgende Beispiel findet Daten mit status:"A" in der Collection orders, gruppiert nach cust_id und berechnet die Summe von amount.
Verwendung von MapReduce
Betrachten Sie die folgende Dokumentstruktur zum Speichern von Benutzerartikeln. Das Dokument speichert den user_name des Benutzers und das status-Feld des Artikels:
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "mark",
"status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "mark",
"status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "mark",
"status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "mark",
"status":"active"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "mark",
"status":"disabled"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "example",
"status":"disabled"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "example",
"status":"disabled"
})
WriteResult({ "nInserted" : 1 })
>db.posts.insert({
"post_text": "Example,最全的技术文档。",
"user_name": "example",
"status":"active"
})
WriteResult({ "nInserted" : 1 })
Nun verwenden wir die mapReduce-Funktion auf der posts-Collection, um veröffentlichte Artikel auszuwählen (status:"active"), nach user_name zu gruppieren und die Anzahl der Artikel für jeden Benutzer zu berechnen:
>db.posts.mapReduce(
function() { emit(this.user_name,1); },
function(key, values) {return Array.sum(values)},
{
query:{status:"active"},
out:"post_total"
}
)
Die Ausgabe des obigen mapReduce ist:
{
"result" : "post_total",
"timeMillis" : 23,
"counts" : {
"input" : 5,
"emit" : 5,
"reduce" : 1,
"output" : 2
},
"ok" : 1
}
Das Ergebnis zeigt, dass es 5 Dokumente gibt, die die Abfragebedingung erfüllen (status:"active"), 5 Schlüssel-Wert-Paar-Dokumente in der Map-Funktion erzeugt wurden und schließlich die Reduce-Funktion die identischen Schlüsselwerte in 2 Gruppen zusammengefasst hat.
Spezifische Parameterbeschreibung:
- result: der Name der Sammlung, die die Ergebnisse speichert. Dies ist eine temporäre Sammlung, die automatisch gelöscht wird, nachdem die MapReduce-Verbindung geschlossen wurde.
- timeMillis: die Zeit, die für die Ausführung benötigt wird, in Millisekunden
- input: die Anzahl der Dokumente, die die Bedingung erfüllen und an die map-Funktion gesendet werden
- emit: die Anzahl, wie oft emit in der map-Funktion aufgerufen wird, d. h. die Gesamtdatenmenge in allen Sammlungen
- output: die Anzahl der Dokumente in der Ergebnissammlung(count ist sehr hilfreich beim Debuggen)
- ok: ob es erfolgreich war, 1 für Erfolg
- err: Wenn es fehlschlägt, kann der Fehlergrund hier gefunden werden. Aus Erfahrung ist der Grund jedoch relativ vage und nicht sehr nützlich.
Verwenden Sie den find-Operator, um die Abfrageergebnisse von mapReduce anzuzeigen:
> var map=function() { emit(this.user_name,1); }
> var reduce=function(key, values) {return Array.sum(values)}
> var options={query:{status:"active"},out:"post_total"}
> db.posts.mapReduce(map,reduce,options)
{ "result" : "post_total", "ok" : 1 }
> db.post_total.find();
Die obige Abfrage zeigt die folgenden Ergebnisse an:
{ "_id" : "mark", "value" : 4 }
{ "_id" : "example", "value" : 1 }
In ähnlicher Weise kann MapReduce verwendet werden, um große, komplexe Aggregationsabfragen zu erstellen.
Die Map-Funktion und die Reduce-Funktion können mit JavaScript implementiert werden, was MapReduce sehr flexibel und leistungsstark macht.
Andere Erweiterungen