Descripción
Define variables temporales a las que se puede hacer referencia en etapas posteriores de la canalización.
Las variables creadas en la etapa let(...) no se incluyen en los resultados finales, a menos que se asignen explícitamente a un campo en una etapa posterior (p.ej., con add_fields(...) o select(...)). Esto te permite simplificar la lógica compleja dividiéndola en componentes más pequeños y reutilizables sin sobrecargar los documentos de salida. La etapa let(...) es particularmente útil para las canalizaciones secundarias correlacionadas, en las que una canalización secundaria necesita hacer referencia a un valor del alcance del documento principal.
Ejemplos
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();
Comportamiento
Variables frente a campos
Mientras que los campos representan los datos almacenados en los documentos, las variables son valores temporales que solo existen durante la ejecución de la canalización.
| Campos | Variables | |
|---|---|---|
| Objetivo | acceder a campos o almacenarlos en documentos | Generar o acceder a valores temporales durante la ejecución de la canalización |
| Uso del SDK | field("name") |
variable("name") |
| Permiso | local al documento actual | Global para la canalización y las subcanalizaciones |
| Referencias sin definir | se evalúa como absent |
genera un error de tiempo de ejecución |
Alcance:
Si bien los campos se limitan al documento local, las variables se definen en un alcance independiente y siguen siendo accesibles en todas las etapas hasta la primera aparición de una etapa que "combina" varios documentos (como aggregate(...) o distinct(...)). Las etapas que "combinan" varios documentos no permiten que se usen referencias de variables después, ya que, al combinar los resultados de la etapa anterior, ya no hay un valor para la variable.
Hazlo: Haz referencia a una variable después de filtrar los campos del documento.
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();
No: Haz referencia a una variable después de una agregación.
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();
Referencias no definidas:
Si bien hacer referencia a un campo no definido está bien (y solo se evalúa como absent), intentar hacer referencia a una variable no definida fallará durante la validación de la solicitud. En este sentido, las referencias de campo se pueden considerar como una búsqueda en un mapa en el tiempo de ejecución, mientras que las referencias de variables son más similares a las variables en un lenguaje de programación compilado de forma estática.
Alcance global y subconsultas
Las variables son esenciales cuando se trabaja con canalizaciones anidadas. Una canalización secundaria se ejecuta en su propio alcance y solo puede acceder a los campos de los documentos que está procesando. Para usar un valor del documento "principal" dentro de una subconsulta, primero debes definirlo como una variable con la etapa 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 superpuestas
Si se define una variable con un nombre que ya se definió en una etapa let(...) anterior, se sobrescribirá la variable anterior. Se puede usar para actualizar el estado temporal a medida que avanza la canalización.
Las variables a las que se hace referencia en la subcanalización siguen las reglas de alcance léxico que se encuentran en muchos lenguajes de programación y hacen referencia a las variables con el mismo nombre definidas por la canalización más cercana (principal).
Comparación con add_fields(...)
La etapa let(...) se comporta de manera similar a la etapa add_fields(...), pero, en lugar de agregar campos al documento, asigna valores a las variables.