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.