說明
定義可在管道後續階段參照的暫時變數。
除非明確指派給後續階段的欄位 (例如使用 add_fields(...) 或 select(...)),否則在 let(...) 階段建立的變數不會納入最終結果。您可以將複雜的邏輯分解為較小的可重複使用元件,簡化邏輯,同時避免輸出文件雜亂無章。let(...) 階段特別適合用於相關子管道,因為子管道需要參照父項文件範圍中的值。
範例
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();
行為
變數與欄位
欄位代表儲存在文件中的資料,變數則是僅在管道執行期間存在的暫時值。
| 欄位 | 變數 | |
|---|---|---|
| 目的 | 存取欄位或將欄位儲存至文件中 | 在管道執行期間產生或存取暫時值 |
| SDK 使用情形 | field("name") |
variable("name") |
| 範圍 | 目前文件所在位置 | 從全域到管道和子管道 |
| 未定義的參照 | 評估結果為 absent |
產生執行階段錯誤 |
範圍:
欄位會限定在本地文件中,變數則是在個別範圍中定義,且在「合併」多個文件的階段首次出現之前,變數在各階段中都可存取 (例如 aggregate(...) 或 distinct(...))。「合併」多個文件的階段不允許之後使用變數參照,因為合併先前階段的結果後,變數就不再有單一值。
做法:篩選文件欄位後,再參照變數。
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();
請勿:在匯總後參照變數。
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();
未定義的參照:
參考未定義的欄位沒問題 (只會評估為 absent),但嘗試參考未定義的變數時,要求驗證會失敗。就這個意義而言,欄位參照可視為在執行階段執行地圖中的查閱作業,而變數參照則較類似於靜態編譯程式設計語言中的變數。
全域範圍和子查詢
使用巢狀管道時,變數至關重要。子管道會在自己的範圍內執行,且只能存取目前處理的文件欄位。如要在子查詢中使用「父項」文件中的值,必須先使用 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();
重疊變數
如果定義的變數名稱與先前 let(...) 階段中定義的名稱相同,系統會覆寫先前的變數。這可用於在管道進展時更新暫時狀態。
子管道中參照的變數會遵循許多程式設計語言中的詞彙範圍規則,並參照最接近 (父項) 管道定義的同名變數。
與「add_fields(...)」比較
let(...) 階段的行為與 add_fields(...) 階段類似,但會將值指派給變數,而不是在文件中新增欄位。