תיאור
בשלב הקלט subcollection(...) קל לבצע הצטרפות של הורה-צאצא באמצעות השדה המובנה __name__.
אפשר לשרשר שלבים נוספים לשלב subcollection(...) כדי לבצע סינון או צבירה של המסמכים המקוננים. שימו לב: כל הפניות לשדות שמשמשות בשלבים הבאים מתייחסות למסמכים מהאוסף המקונן, ולא למסמך האב. כדי להתייחס לשדות בהיקף ההורה, צריך קודם להשתמש בשלב let(...) כדי להגדיר משתנים, ואז להתייחס למשתנים האלה בהיקף המקומי.
דוגמאות
Node.js
db.pipeline()
.collection("/restaurants")
.add_fields(subcollection("reviews")
.aggregate(average("rating").as("avg_rating"))
.toScalarExpression()
.as("avg_rating"))
התנהגות
השלב subcollection(...) צריך לשמש בהקשר של שאילתת משנה. הוא משתמש ב-__name__ (הפניה למסמך) של המסמך הנוכחי בהיקף ההורה כדי לקבוע איזו קולקציית משנה צריך לאחזר. לדוגמה, אם מסמך האב הוא /restaurants/pizza-place, אז subcollection("reviews") מחזיר את כל המסמכים מהאוסף /restaurants/pizza-place/reviews.
אם שונה השם של הפניה למסמך, או אם אי אפשר להגדיר שדה עם __name__, צריך לכתוב את הצירוף באופן ידני, למשל:
Node.js
db.pipeline()
.collection("/restaurants")
.let(field("__name__").as("restaurant_name"))
.add_fields(db.pipeline()
.collectionGroup("reviews")
.where(field("__name__").parent().equals(variable("restaurant_name")))
.aggregate(average("rating").as("avg_rating"))
.toScalarExpression()
.as("avg_rating"))
עדיין אפשרי, כי השלב הזה הוא בעצם קיצור דרך תחבירי לפורמט המורכב יותר של הצטרפות.
למסמכים הבאים:
Node.js
const restaurant1 = db.collection("restaurants").document("pizza-place");
const restaurant2 = db.collection("restaurants").document("urban-bite");
const restaurant3 = db.collection("restaurants").document("nacho-house");
await restaurant1.create({ name: "Pizza Place" });
await restaurant2.create({ name: "Urban Bite" });
await restaurant3.create({ name: "Nacho House" });
await restaurant1.collection("reviews").doc("1").create({ rating: 5 });
await restaurant1.collection("reviews").doc("1").create({ rating: 2 });
await restaurant2.collection("reviews").doc("1").create({ rating: 3 });
await restaurant2.collection("reviews").doc("1").create({ rating: 4 });
await restaurant2.collection("reviews").doc("1").create({ rating: 5 });
השאילתה הבאה מאחזרת כל מסעדה ומסכמת את הביקורות שלה בשדה review_summary חדש:
Node.js
const results = await db.pipeline()
.collectionGroup("restaurants")
.add_fields(subcollection("reviews")
.aggregate(
countAll().as("review_count"),
average("rating").as("avg_rating"))
.asScalarExpression()
.as("review_summary"))
.execute();
ומפיקה את התוצאות הבאות:
{ name: "Pizza Place", review_summary: { review_count: 2, avg_rating: 3.5 } },
{ name: "Urban Bite", review_summary: { review_count: 3, avg_rating: 4.0 } },
{ name: "Nacho House", review_summary: { review_count: 0, avg_rating: null } },