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 de forma explícita 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 desordenar los documentos de salida. La etapa let(...) es especialmente útil para las subcanalizaciones correlacionadas, en las que una subcanalización necesita hacer referencia a un valor del alcance del documento superior.

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 en comparación con 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")
Alcance local para el documento actual global para la canalización y las subcanalizaciones
Referencias no definidas 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 "une" varios documentos (como aggregate(...) o distinct(...)). Las etapas que "unen" varios documentos no permiten que se usen referencias de variables después, ya que, al unir los resultados de la etapa anterior, ya no hay un valor para la variable.

Qué hacer: 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();

Qué no hacer: No hagas 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 ver como la realización de 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 subcanalización se ejecuta en su propio alcance y solo puede acceder a los campos de los documentos que está procesando actualmente. Para usar un valor del documento "superior" 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 defines una variable con un nombre que ya se definió en una etapa let(...) anterior, se sobrescribirá la variable anterior. Esto 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 se refieren a las variables con el mismo nombre definidas por la canalización más cercana (superior).

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.