Ich habe eine MongoDB-Sammlung, deren Dokumente mehrere Verschachtelungsebenen verwenden, aus denen ich ein mehrdimensionales Array extrahieren möchte, das aus einer Teilmenge ihrer Felder kompiliert wurde. Ich habe eine Lösung, die gerade für mich funktioniert, aber ich möchte dieses Konzept der "Idempotenz" und ihre Konsequenzen im Zusammenhang mit der Reduktionsfunktion besser verstehen.
%Vor%Und hier sind die Map / Reduce-Funktionen
%Vor%Daten werden in einer nützlichen Struktur zurückgegeben, die ich neu formatiere / sortiere, um sie für das Zeichnen fertigzustellen.
%Vor%Endlich ...
%Vor%TL; DR: Was ist das erwartete Verhalten beim übergeordneten "Chunking" der Array-Ergebnisse?
Ich verstehe, dass die reduce-Funktion mehrfach auf Arrays von emittierten Werten aufgerufen werden kann. Deshalb gibt es mehrere "Chunks" der vollständigen Arrays und nicht ein einzelnes Array. Die Array-Chunks sind in der Regel 25-50 Elemente und es ist einfach genug, dies in finalize () zu bereinigen. Ich concat () die Arrays, verschachteln sie als [Zeit, Wert] und sortieren. Aber was ich wirklich wissen möchte, ist, ob dies komplexer werden kann:
1) Wird das Chunking aufgrund meines Codes, der MongoDB-Implementierung oder des Map / Reduce-Algorithmus selbst beobachtet?
2) Wird es jemals eine tiefere (rekursive) Verschachtelung von Array-Chunks in Shard-Konfigurationen oder sogar nur aufgrund meiner vorschnellen Implementierung geben? Dies würde die concat () Methode brechen.
3) Gibt es einfach eine bessere Strategie, Array-Ergebnisse zu erhalten, wie oben gezeigt?
Ich nahm Thomas Rat und schrieb es neu, um Arrays zu emittieren. Es macht absolut keinen Sinn, die Werte aufzuteilen.
%Vor%Nun ist die Ausgabe ähnlich:
%Vor%Und ich habe diese finalize-Funktion verwendet, um die Array-Chunks zu verketten und sie zu sortieren.
%Vor%Was gut funktioniert:
%Vor%Ich denke, die einzige Frage, die mich nervt, ist, ob diese Array.concat.apply ([], values.value) vertrauenswürdig ist, um die Ausgabe von reduce die ganze Zeit zu bereinigen.
Ich habe die Dokumentstruktur seit dem ursprünglichen Beispiel modifiziert, aber das ändert nur das Beispiel, indem ich die Map-Funktion wirklich einfach mache.
Ich versuche immer noch mein Gehirn darum herumzulegen, warum Array.prototype.push.apply (result, V.data) so anders funktioniert als result.push (V.data) ... aber es funktioniert.
> %Vor%Es hat dieselbe Ausgabe wie direkt über der Überschrift LETZTE BEARBEITUNG.
Danke, Thomas!
Das "chunking" kommt aus Ihrem Code: Der Werteparameter Ihrer reduce-Funktion kann entweder {time:<timestamp>,value:<value>}
von Ihrer Kartenfunktion oder {time:[<timestamps>],value:[<values]}
von einem vorherigen Aufruf Ihrer reduce-Funktion enthalten.
Ich weiß nicht, ob das in der Praxis passieren wird, aber es kann theoretisch passieren.
Lassen Sie einfach Ihre Kartenfunktion dieselbe Art von Objekten ausgeben, die Ihre reduce-Funktion zurückgibt, d. h. emit(<id>, {time: [ts], value: [P[1]]})
, und ändern Sie die reduce-Funktion entsprechend, also Array.push.apply(result.time, V.time)
und ähnlich für result.value
.
Nun, ich verstehe eigentlich nicht, warum Sie nicht ein Array von Zeit / Wert-Paaren anstelle eines Paares von Arrays verwenden, dh emit(<id>, { pairs: [ {time: ts, value: P[1] ] })
oder emit(<id>, { pairs: [ [ts, P[1]] ] })
in der Map-Funktion und Array.push.apply(result.pairs, V.pairs)
in der Funktion reduzieren. Auf diese Weise brauchen Sie nicht einmal die Finalize-Funktion (außer vielleicht das Array aus der pairs -Eigenschaft auszupacken): Da die reduce-Funktion kein Array zurückgeben kann, müssen Sie es so einwickeln ein Objekt)