Izinkan

Deskripsi

Tentukan variabel sementara yang dapat dirujuk pada tahap selanjutnya dari pipeline.

Variabel yang dibuat di tahap let(...) tidak disertakan dalam hasil akhir kecuali jika ditetapkan secara eksplisit ke kolom di tahap berikutnya (misalnya, menggunakan add_fields(...) atau select(...)). Dengan demikian, Anda dapat menyederhanakan logika yang kompleks dengan memecahnya menjadi komponen yang lebih kecil dan dapat digunakan kembali tanpa membuat dokumen output menjadi berantakan. Tahap let(...) sangat berguna untuk sub-pipeline yang berkorelasi, yang mana sub-pipeline perlu mereferensikan nilai dari cakupan dokumen induk.

Contoh

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

Perilaku

Variabel versus Kolom

Meskipun kolom merepresentasikan data yang disimpan dalam dokumen, variabel adalah nilai sementara yang hanya ada selama eksekusi pipeline.

Kolom Variabel
Tujuan mengakses atau menyimpan kolom ke dalam dokumen membuat atau mengakses nilai sementara selama eksekusi pipeline
Penggunaan SDK field("name") variable("name")
Cakupan lokal ke dokumen saat ini global ke pipeline dan sub-pipeline
Referensi Tidak Ditentukan mengevaluasi ke absent menghasilkan error runtime

Cakupan:

Meskipun kolom dicakup ke dokumen lokal, variabel ditentukan dalam cakupan terpisah dan tetap dapat diakses di seluruh tahap hingga kemunculan pertama tahap yang "menggabungkan" beberapa dokumen (seperti aggregate(...) atau distinct(...)). Tahap yang "menggabungkan" beberapa dokumen tidak mengizinkan referensi variabel digunakan setelahnya karena dengan menggabungkan hasil tahap sebelumnya, tidak ada lagi satu nilai untuk variabel.

Lakukan: Merujuk variabel setelah memfilter kolom dokumen.

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

Jangan: Merujuk variabel setelah agregasi.

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

Referensi yang Tidak Ditentukan:

Meskipun mereferensikan kolom yang tidak ditentukan tidak masalah (dan hanya dievaluasi ke absent), mencoba mereferensikan variabel yang tidak ditentukan akan gagal selama validasi permintaan. Dalam hal ini, referensi kolom dapat dilihat sebagai melakukan pencarian di peta saat runtime, sedangkan referensi variabel lebih mirip dengan variabel dalam bahasa pemrograman yang dikompilasi secara statis.

Cakupan Global dan Subkueri

Variabel sangat penting saat bekerja dengan pipeline bertingkat. Sub-pipeline dieksekusi dalam cakupannya sendiri dan hanya dapat mengakses kolom dokumen yang sedang diproses. Untuk menggunakan nilai dari dokumen "induk" di dalam subkueri, Anda harus terlebih dahulu menentukannya sebagai variabel menggunakan tahap 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();

Variabel yang Tumpang-Tindih

Menentukan variabel dengan nama yang sudah ditentukan di tahap let(...) sebelumnya akan menimpa variabel sebelumnya. Hal ini dapat digunakan untuk memperbarui status sementara saat pipeline berlangsung.

Variabel yang dirujuk dalam sub-pipeline mengikuti aturan cakupan leksikal seperti yang ditemukan dalam banyak bahasa pemrograman dan mengacu pada variabel dengan nama yang sama yang ditentukan oleh pipeline terdekat (induk).

Perbandingan dengan add_fields(...)

Tahap let(...) berperilaku serupa dengan tahap add_fields(...), tetapi alih-alih menambahkan kolom ke dokumen, tahap ini menetapkan nilai ke variabel.