زیرمجموعه

شرح

مرحله ورودی 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"))

is still possible as fundamentally this stage is just syntactic sugar over this more complex join format.

برای اسناد زیر:

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 } },