תיאור
הגדרת משתנים זמניים שאפשר להפנות אליהם בשלבים הבאים של צינור העיבוד.
משתנים שנוצרו בשלב let(...) לא נכללים בתוצאות הסופיות, אלא אם הם מוקצים במפורש לשדה בשלב מאוחר יותר (למשל באמצעות add_fields(...) או select(...)). כך אפשר לפשט לוגיקה מורכבת על ידי פירוק שלה לרכיבים קטנים יותר לשימוש חוזר, בלי להעמיס על מסמכי הפלט. השלב 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(...), אבל במקום להוסיף שדות למסמך, הוא מקצה ערכים למשתנים.