Deskripsi
Tahap input subcollection(...) memudahkan untuk melakukan penggabungan induk-turunan
menggunakan kolom __name__ bawaan.
Tahap tambahan dapat dirangkai ke tahap subcollection(...) untuk melakukan
pemfilteran atau penggabungan pada dokumen bertingkat. Perhatikan bahwa referensi
kolom yang digunakan pada tahap berikutnya mengacu pada dokumen dari koleksi
bertingkat, bukan dokumen induk. Untuk merujuk ke kolom dalam cakupan induk,
gunakan terlebih dahulu tahap let(...) untuk menentukan variabel, lalu
rujuk variabel tersebut dalam cakupan lokal.
Contoh
Node.js
db.pipeline()
.collection("/restaurants")
.add_fields(subcollection("reviews")
.aggregate(average("rating").as("avg_rating"))
.toScalarExpression()
.as("avg_rating"))
Perilaku
Tahap subcollection(...) harus digunakan dalam konteks
subkueri. Fungsi ini menggunakan __name__ (referensi dokumen) dari dokumen saat ini dalam cakupan induk untuk menentukan subkoleksi yang akan diambil. Misalnya, jika dokumen induk adalah /restaurants/pizza-place, maka
subcollection("reviews") akan menampilkan semua dokumen dari
koleksi /restaurants/pizza-place/reviews.
Jika referensi dokumen telah diganti namanya, atau tidak mungkin menentukan
kolom dengan __name__, maka tulis gabungan secara manual seperti:
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"))
masih memungkinkan karena pada dasarnya tahap ini hanyalah pintasan sintaksis atas format gabungan yang lebih kompleks ini.
Untuk dokumen berikut:
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 });
Kueri berikut mengambil setiap restoran dan merangkum ulasannya dalam kolom review_summary baru:
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();
dan menghasilkan hasil berikut:
{ 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 } },