Dejar

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.