Let

Beschreibung

Definieren Sie temporäre Variablen, auf die in nachfolgenden Phasen der Pipeline verwiesen werden kann.

Variablen, die in der let(...) Phase erstellt wurden, sind nicht in den Endergebnissen enthalten es sei denn, sie werden in einer späteren Phase explizit einem Feld 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 Unterpipelines, bei denen eine Unterpipeline auf einen Wert aus dem Bereich des übergeordneten Dokuments verweisen 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

Während Felder Daten darstellen, die in Dokumenten gespeichert sind, sind Variablen temporäre Werte, die nur während der Ausführung der Pipeline vorhanden sind.

Felder Variablen
Zweck Auf Felder in Dokumenten zugreifen oder sie dort 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 Unterpipelines
Nicht definierte Referenzen Wird zu absent ausgewertet Generiert Laufzeitfehler

Umfang :

Während Felder auf das lokale Dokument beschränkt sind, werden Variablen in einem separaten Bereich definiert und bleiben über Phasen hinweg zugänglich, bis die erste Phase erreicht wird, in der mehrere Dokumente zusammengeführt werden (z. B. aggregate(...) oder distinct(...)). In Phasen, in denen mehrere Dokumente zusammengeführt werden, können keine Variablenreferenzen mehr verwendet werden, da durch das Zusammenführen der Ergebnisse der vorherigen Phase kein einzelner Wert mehr für die Variable vorhanden ist.

Empfehlung: 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 empfehlenswert: Verweisen Sie nach einer Aggregation nicht 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 :

Während das Verweisen auf ein nicht definiertes Feld in Ordnung ist (und einfach zu absent ausgewertet wird), schlägt der Versuch, auf eine nicht definierte Variable zu verweisen, bei der Anfragevalidierung fehl. In diesem Sinne können Feldreferenzen als Suche in einer Map zur Laufzeit betrachtet werden, während Variablenreferenzen eher Variablen in einer statisch kompilierten Programmiersprache ähneln.

Globaler Bereich und Unterabfragen

Variablen sind unerlässlich, wenn Sie mit verschachtelten Pipelines arbeiten. Eine Unterpipeline wird in einem 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();

Überlappende Variablen

Wenn Sie eine Variable mit einem Namen definieren, der bereits in einer vorherigen Phase let(...) definiert wurde, wird die vorherige Variable überschrieben. So können Sie den temporären Status im Laufe der Pipeline aktualisieren.

Variablen, auf die in Unterpipelines verwiesen wird, folgen den Regeln für den lexikalischen Bereich , wie sie in vielen Programmiersprachen zu finden sind. Sie beziehen sich auf die Variablen unter dem selben Namen, die von der nächstgelegenen (übergeordneten) Pipeline definiert wurden.

Vergleich mit add_fields(...)

Die let(...) Phase verhält sich ähnlich wie die add_fields(...) Phase. Anstatt jedoch Felder zum Dokument hinzuzufügen, werden Variablen Werte zugewiesen.