Beschreibung
Definieren Sie temporäre Variablen, auf die in nachfolgenden Phasen der Pipeline verwiesen werden kann.
Variablen, die in der Phase let(...) erstellt werden, sind nicht in den Endergebnissen enthalten, es sei denn, sie werden explizit einem Feld in einer späteren Phase zugewiesen (z.B. mit add_fields(...) oder select(...)). So können Sie komplexe Logik vereinfachen, indem Sie sie in kleinere, wiederverwendbare Komponenten aufteilen, ohne die Ausgabedokumente zu überladen. Die Phase let(...) ist besonders nützlich für korrelierte untergeordnete Pipelines, bei denen in einer untergeordneten Pipeline auf einen Wert aus dem Bereich des übergeordneten Dokuments verwiesen werden muss.
Beispiele
Node.js
const results = await db.pipeline()
.collection("/awards")
// `let(...)` referred to as `define(...)` in the Web SDK.
.define(rand().as("r"))
.addFields(
switchOn(
lessThan(variable("r"), 0.05), constant("rare"),
lessThan(variable("r"), 0.25), constant("uncommon"),
constant("common")).as("random_score"))
.execute();
Verhalten
Variablen im Vergleich zu Feldern
Felder stellen Daten dar, die in Dokumenten gespeichert sind, während Variablen temporäre Werte sind, die nur während der Ausführung der Pipeline vorhanden sind.
| Felder | Variablen | |
|---|---|---|
| Zweck | auf Felder in Dokumenten zugreifen oder sie darin speichern | temporäre Werte während der Pipelineausführung generieren oder darauf zugreifen |
| SDK-Nutzung | field("name") |
variable("name") |
| Umfang | lokal für das aktuelle Dokument | Global für Pipeline und untergeordnete Pipelines |
| Nicht definierte Referenzen | wird mit absent ausgewertet |
Laufzeitfehler wird generiert |
Umfang:
Felder sind auf das lokale Dokument beschränkt, Variablen werden in einem separaten Bereich definiert und bleiben über alle Phasen hinweg zugänglich, bis zur ersten Phase, in der mehrere Dokumente zusammengeführt werden (z. B. aggregate(...) oder distinct(...)). In Phasen, in denen mehrere Dokumente zusammengeführt werden, können danach keine Variablenverweise mehr verwendet werden, da durch das Zusammenführen der Ergebnisse der vorherigen Phase kein einzelner Wert für die Variable mehr vorhanden ist.
Vorgehensweise: Verweisen Sie auf eine Variable, nachdem Sie die Felder des Dokuments gefiltert haben.
Node.js
const results = db.pipeline()
.collection("/awards")
.define(min(field("score").abs(), constant(100)).as("normalized_score"))
.select(field("__name__"), field("owner_id"))
// Successfully able to use the variable.
.where(variable("normalized_score").greaterThan(10))
.execute();
Nicht: Verweisen Sie nach einer Aggregation auf eine Variable.
Node.js
const results = db.pipeline()
.collection("/awards")
.define(min(field("score").abs(), constant(100)).as("normalized_score"))
.aggregate({
accumulators: [ field("score").avg().as("avg_score") ],
groups: [ field("owner_id") ]
})
// Attempting to use the variable throws a request validation error.
.where(variable("normalized_score").greaterThan(10))
.execute();
Nicht definierte Referenzen:
Es ist in Ordnung, auf ein nicht definiertes Feld zu verweisen (es wird einfach als absent ausgewertet). Wenn Sie jedoch versuchen, auf eine nicht definierte Variable zu verweisen, schlägt die Anfragevalidierung fehl. In diesem Sinne können Feldreferenzen als Suche in einer Karte zur Laufzeit betrachtet werden, während Variablenreferenzen eher Variablen in einer statisch kompilierten Programmiersprache ähneln.
Globaler Bereich und Unterabfragen
Variablen sind für die Arbeit mit verschachtelten Pipelines unerlässlich. Eine untergeordnete Pipeline wird in ihrem eigenen Bereich ausgeführt und kann nur auf die Felder der Dokumente zugreifen, die sie gerade verarbeitet. Wenn Sie einen Wert aus dem „übergeordneten“ Dokument in einer Unterabfrage verwenden möchten, müssen Sie ihn zuerst mit der Phase let(...) als Variable definieren.
Node.js
// Fetch reviewers alongside their negative reviews.
const pipeline = db.pipeline()
.collection("/reviewers")
// `let(...)` referred to as `define(...)` in the Web SDK.
.define(field("__name__").as("reviewer_name"))
.select("__name__", array(db.pipeline().collectionGroup("reviews")
.where(field("author").equals(variable("reviewer_name")))
.where(field("rating").lessThan(2))
.select("review", "rating")).as("negative_reviews"))
.execute();
Sich überschneidende Variablen
Wenn Sie eine Variable mit einem Namen definieren, der bereits in einer vorherigen let(...)-Phase definiert wurde, wird die vorherige Variable überschrieben. Damit lässt sich der temporäre Status im Laufe der Pipeline aktualisieren.
Variablen, auf die in der untergeordneten Pipeline verwiesen wird, folgen den Regeln für den lexikalischen Gültigkeitsbereich, die in vielen Programmiersprachen zu finden sind. Sie beziehen sich auf die Variablen mit demselben Namen, die von der nächstgelegenen (übergeordneten) Pipeline definiert werden.
Vergleich mit add_fields(...)
Die Phase let(...) verhält sich ähnlich wie die Phase add_fields(...). Anstatt Felder zum Dokument hinzuzufügen, werden hier jedoch Variablen Werte zugewiesen.