Vamos

Descrição

Defina variáveis temporárias que podem ser referenciadas em etapas subsequentes do pipeline.

As variáveis criadas na etapa let(...) não são incluídas nos resultados finais a menos que sejam explicitamente atribuídas a um campo em uma etapa posterior (por exemplo, usando add_fields(...) ou select(...)). Isso permite simplificar a lógica complexa dividindo-a em componentes menores e reutilizáveis sem sobrecarregar os documentos de saída. A etapa let(...) é especialmente útil para subpipelines correlacionados, em que um subpipeline precisa referenciar um valor do escopo do documento pai.

Exemplos

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

Comportamento

Variáveis x campos

Enquanto os campos representam dados armazenados em documentos, as variáveis são valores temporários que existem apenas durante a execução do pipeline.

Campos Variáveis
Finalidade acessar ou armazenar campos em documentos gerar ou acessar valores temporários durante a execução do pipeline
Uso do SDK field("name") variable("name")
Escopo local para o documento atual global para pipeline e subpipelines
Referências indefinidas avalia como absent gera erro de execução

Escopo :

Enquanto os campos são definidos no documento local, as variáveis são definidas em um escopo separado e permanecem acessíveis em todas as etapas até a primeira ocorrência de uma etapa que "mescla" vários documentos (como aggregate(...) ou distinct(...)). As etapas que "mesclam" vários documentos não permitem que referências de variáveis sejam usadas depois, porque, ao mesclar os resultados da etapa anterior, não há mais um valor para a variável.

Faça: referencie uma variável depois de filtrar os campos do 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();

Não faça: referencie uma variável após uma agregação.

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

Referências indefinidas :

Embora referenciar um campo indefinido seja bom (e apenas avalie como absent), tentar referenciar uma variável indefinida falhará durante a validação da solicitação. Nesse sentido, as referências de campo podem ser consideradas como a realização de uma pesquisa em um mapa no ambiente de execução, enquanto as referências de variáveis são mais parecidas com variáveis em uma linguagem de programação compilada estaticamente.

Escopo global e subconsultas

As variáveis são essenciais ao trabalhar com pipelines aninhados. Um subpipeline é executado no próprio escopo e só pode acessar os campos dos documentos que está processando. Para usar um valor do documento "pai" em uma subconsulta, primeiro defina-o como uma variável usando a 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();

Variáveis sobrepostas

Definir uma variável com um nome que já foi definido em uma etapa let(...) anterior vai substituir a variável anterior. Isso pode ser usado para atualizar o estado temporário à medida que o pipeline avança.

As variáveis referenciadas no subpipeline seguem regras de escopo léxico , como encontradas em muitas linguagens de programação, e se referem às variáveis com o mesmo nome definido pelo pipeline mais próximo (pai).

Comparação com add_fields(...)

A etapa let(...) se comporta de maneira semelhante à etapa add_fields(...), mas, em vez de adicionar campos ao documento, ela atribui valores a variáveis.