Passons

Description

Définissez des variables temporaires auxquelles vous pourrez faire référence dans les étapes suivantes du pipeline.

Les variables créées à l'étape let(...) ne sont pas incluses dans les résultats finaux sauf si elles sont explicitement attribuées à un champ à une étape ultérieure (par exemple, à l'aide de add_fields(...) ou select(...)). Cela vous permet de simplifier une logique complexe en la divisant en composants plus petits et réutilisables, sans encombrer les documents de sortie. L'étape let(...) est particulièrement utile pour les sous-pipelines corrélés, où un sous-pipeline doit faire référence à une valeur du champ d'application du document parent.

Exemples

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();

Comportement

Variables et champs

Alors que les champs représentent les données stockées dans les documents, les variables sont des valeurs temporaires qui n'existent que pendant l'exécution du pipeline.

Champs Variables
Objectif accéder à des champs ou les stocker dans des documents générer des valeurs temporaires ou y accéder pendant l'exécution du pipeline
Utilisation du SDK field("name") variable("name")
Champ d'application local au document actuel global au pipeline et aux sous-pipelines
Références non définies prend la valeur absent génère une erreur d'exécution

Champ d'application :

Alors que les champs sont limités au document local, les variables sont définies dans un champ d'application distinct et restent accessibles dans toutes les étapes jusqu'à la première occurrence d' une étape qui "fusionne" plusieurs documents (comme aggregate(...) ou distinct(...)). Les étapes qui "fusionnent" plusieurs documents n'autorisent pas l'utilisation de références de variables par la suite, car la fusion des résultats de l'étape précédente ne laisse plus qu'une seule valeur pour la variable.

À faire : faire référence à une variable après avoir filtré les champs du document.

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();

À ne pas faire : faire référence à une variable après une agrégation.

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();

Références non définies :

Bien qu'il soit possible de faire référence à un champ non défini (qui prend simplement la valeur absent), toute tentative de référence à une variable non définie échouera lors de la validation de la requête. En ce sens, les références de champ peuvent être considérées comme une recherche dans une carte au moment de l'exécution, tandis que les références de variable sont plus semblables aux variables dans un langage de programmation compilé de manière statique.

Champ d'application global et sous-requêtes

Les variables sont essentielles lorsque vous travaillez avec des pipelines imbriqués. Un sous-pipeline s'exécute dans son propre champ d'application et ne peut accéder qu'aux champs des documents qu'il traite actuellement. Pour utiliser une valeur du document "parent" dans une sous-requête, vous devez d'abord la définir comme variable à l'aide de l'étape let(...).

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();

Variables qui se chevauchent

La définition d'une variable avec un nom déjà défini dans une étape let(...) précédente remplace la variable précédente. Cela peut être utilisé pour mettre à jour l'état temporaire au fur et à mesure de l'avancement du pipeline.

Les variables référencées dans le sous-pipeline suivent les règles de champ d'application lexicales que l'on trouve dans de nombreux langages de programmation et font référence aux variables portant le même nom définies par le pipeline le plus proche (parent).

Comparaison avec add_fields(...)

L'étape let(...) se comporte de la même manière que l'étape add_fields(...), mais au lieu d'ajouter des champs au document, elle attribue des valeurs aux variables.