Mulai menggunakan Kueri Pipeline
Latar belakang
Operasi Pipeline menyediakan antarmuka kueri baru untuk
Firestore yang mendukung fungsi kueri tingkat lanjut dan ekspresi
kompleks. Library ini memperkenalkan banyak fungsi baru, termasuk min(...), max(...), substring(...), regex_match(...), dan array_contains_all(...), serta tahap untuk dapat melakukan transformasi yang kompleks.
Memulai
Untuk menginstal dan menginisialisasi SDK klien, lihat petunjuk di panduan berikut:
Sintaksis
Bagian berikut memberikan ringkasan sintaksis untuk operasi Pipeline.
Konsep
Salah satu perbedaan penting di operasi Pipeline adalah penerapan pengurutan "tahap" secara eksplisit. Dengan ini, Anda dapat mengekspresikan kueri yang lebih kompleks. Namun, ini merupakan perbedaan yang signifikan dari antarmuka kueri yang sudah ada menggunakan operasi Core, yang urutan tahapnya bersifat implisit. Perhatikan contoh operasi Pipeline berikut:
Node.js
db.pipeline() .collection() // Step 1 (start a query with 'collection' scope) .where() // Step 2 (filter collection) .sort() // Step 3 (order results) .limit() // Step 4 (limit results) // Note: Applying a limit before a sort can yield unintended // results (as the limit would be applied before sorting).
Web versi 9
const pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the // pipeline would have unintentional results. .limit(10);
Swift
let pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(Field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort([Field("name").ascending()]) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10)
Kotlin
Android
val pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10)
Java
Android
Pipeline pipeline = db.pipeline() // Step 1: Start a query with collection scope .collection("cities") // Step 2: Filter the collection .where(field("population").greaterThan(100000)) // Step 3: Sort the remaining documents .sort(field("name").ascending()) // Step 4: Return the top 10. Note applying the limit earlier in the pipeline would have // unintentional results. .limit(10);
Python
from google.cloud.firestore_v1.pipeline_expressions import Field pipeline = ( client.pipeline() .collection("cities") .where(Field.of("population").greater_than(100_000)) .sort(Field.of("name").ascending()) .limit(10) )
Inisialisasi
Operasi Pipeline memiliki sintaksis yang sangat familier yang berasal dari kueri Firestore yang ada. Untuk memulai, Anda harus menginisialisasi kueri dengan menulis perintah berikut:
Node.js
const db = new Firestore({ projectId: '' , databaseId: databaseId'}) db.pipeline()
Java
Firestore db = FirestoreOptions.newBuilder().build().getService(); db.pipeline()
Struktur
Ada beberapa istilah yang penting untuk dipahami saat membuat operasi Pipeline: tahap, ekspresi, dan fungsi serta pembungkus subkueri.

Tahap: Pipeline dapat terdiri dari satu atau beberapa tahap. Secara logis, ini mewakili serangkaian langkah (atau tahap) yang dilakukan untuk menjalankan kueri.
Ekspresi: Tahap sering kali menerima ekspresi yang memungkinkan Anda mengekspresikan kueri yang lebih kompleks. Ekspresi bisa jadi sederhana dan terdiri dari satu fungsi
seperti eq("a", 1). Anda juga dapat membuat ekspresi yang lebih kompleks dengan menyusun
ekspresi seperti and(eq("a", 1), eq("b", 2)).
Wrapper Subkueri: Fungsi seperti array() dan scalar() memungkinkan Anda
menyematkan pipeline bertingkat sebagai ekspresi dalam tahap.
Kolom / Konstanta / Variabel
Operasi Pipeline mendukung ekspresi yang kompleks. Oleh karena itu, penting untuk membedakan apakah suatu nilai merepresentasikan kolom, konstanta, atau variabel.
Meskipun kolom merujuk pada data dalam dokumen, dan konstanta memungkinkan
menentukan nilai apa pun sebagai argumen untuk ekspresi, variabel memungkinkan
menentukan & menggunakan nilai sementara yang dicakup ke eksekusi kueri, bukan
dokumen yang sedang diproses. Berikut ringkasan konsep ini, lihat tahap let(...) untuk mengetahui informasi selengkapnya tentang cara membaca & menulis variabel selama eksekusi kueri.
| Kolom | Konstanta | Variabel | |
|---|---|---|---|
| Tujuan | mengakses atau menyimpan kolom ke dalam dokumen | menentukan nilai tetap | menggunakan nilai sementara selama eksekusi pipeline |
| Penggunaan SDK | field("name") |
constant("val") |
variable("name") |
| Cakupan | lokal ke dokumen saat ini | global | global ke pipeline dan sub-pipeline |
| Referensi yang Tidak Ditentukan (Undefined Reference) | mengevaluasi ke absent |
T/A | menghasilkan error runtime |
Contoh:
Node.js
// Here the two parameters "name" and "toronto" could represent fields or constants. db.pipeline() .collection("cities") .where(eq("name","toronto")) // In many cases, it's not necessary to differentiate between the two. In the // case of equality, we will implicit treat the first parameter as a field // reference and the second as a constant. However if you need to override you // can always be explicit with the value types db.pipeline() .collection("cities") .where(eq(Field.of("name"), Constant.of("toronto"))) // In some cases, being explicit is always required. However, it should be // enough to look at the type signature of the expressions to know what //parameters can be used with implicit types, and what should be explicitly specified.
Web versi 9
const pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")));
Swift
let pipeline = db.pipeline() .collection("cities") .where(Field("name").equal(Constant("Toronto")))
Kotlin
Android
val pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")))
Java
Android
Pipeline pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")));
Python
from google.cloud.firestore_v1.pipeline_expressions import Field, Constant pipeline = ( client.pipeline() .collection("cities") .where(Field.of("name").equal(Constant.of("Toronto"))) )
Tahap
Tahap Input
Tahap input merupakan tahap pertama kueri. Tahap ini menentukan
kumpulan dokumen awal yang Anda kueri. Untuk operasi Pipeline, tahap ini sebagian besar mirip dengan kueri yang sudah ada, yang sebagian besar kuerinya dimulai dengan tahap collection(...) atau collection_group(...). Dua tahap input baru adalah
database() dan
documents(...). Dengan
database(), semua dokumen dapat
ditampilkan dalam database. Sementara itu, documents(...)
berfungsi mirip dengan operasi baca secara massal.
Node.js
// Return all restaurants in San Francisco const results = await db.pipeline() .collection("cities/sf/restaurants") .execute(); // Return all restaurants const results = await db.pipeline() .collectionGroup("restaurants") .execute(); // Return all documents across all collections in the database (huge result!) const results = await db.pipeline() .database() .execute(); // Batch read of 3 documents const results = await db.pipeline() .documents( db.collection("cities").doc("SF"), db.collection("cities").doc("DC"), db.collection("cities").doc("NY")) .execute();
Web versi 9
let results; // Return all restaurants in San Francisco results = await execute(db.pipeline().collection("cities/sf/restaurants")); // Return all restaurants results = await execute(db.pipeline().collectionGroup("restaurants")); // Return all documents across all collections in the database (the entire database) results = await execute(db.pipeline().database()); // Batch read of 3 documents results = await execute(db.pipeline().documents([ doc(db, "cities", "SF"), doc(db, "cities", "DC"), doc(db, "cities", "NY") ]));
Swift
var results: Pipeline.Snapshot // Return all restaurants in San Francisco results = try await db.pipeline().collection("cities/sf/restaurants").execute() // Return all restaurants results = try await db.pipeline().collectionGroup("restaurants").execute() // Return all documents across all collections in the database (the entire database) results = try await db.pipeline().database().execute() // Batch read of 3 documents results = try await db.pipeline().documents([ db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ]).execute()
Kotlin
Android
var results: Task<Pipeline.Snapshot> // Return all restaurants in San Francisco results = db.pipeline().collection("cities/sf/restaurants").execute() // Return all restaurants results = db.pipeline().collectionGroup("restaurants").execute() // Return all documents across all collections in the database (the entire database) results = db.pipeline().database().execute() // Batch read of 3 documents results = db.pipeline().documents( db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ).execute()
Java
Android
Task<Pipeline.Snapshot> results; // Return all restaurants in San Francisco results = db.pipeline().collection("cities/sf/restaurants").execute(); // Return all restaurants results = db.pipeline().collectionGroup("restaurants").execute(); // Return all documents across all collections in the database (the entire database) results = db.pipeline().database().execute(); // Batch read of 3 documents results = db.pipeline().documents( db.collection("cities").document("SF"), db.collection("cities").document("DC"), db.collection("cities").document("NY") ).execute();
Python
# Return all restaurants in San Francisco results = client.pipeline().collection("cities/sf/restaurants").execute() # Return all restaurants results = client.pipeline().collection_group("restaurants").execute() # Return all documents across all collections in the database (the entire database) results = client.pipeline().database().execute() # Batch read of 3 documents results = ( client.pipeline() .documents( client.collection("cities").document("SF"), client.collection("cities").document("DC"), client.collection("cities").document("NY"), ) .execute() )
Seperti semua tahap lainnya, urutan hasil dari tahap input ini tidak
stabil. Operator sort(...) harus selalu ditambahkan jika
urutan tertentu diperlukan.
Di mana
Tahap where(...) berfungsi sebagai operasi
filter standar pada dokumen yang dihasilkan dari tahap sebelumnya dan sebagian besar mencerminkan
sintaksis "where" yang ada untuk kueri yang sudah ada. Dokumen apa pun yang ekspresinya menghasilkan nilai
yang bukan true akan difilter dari dokumen yang ditampilkan.
Beberapa pernyataan where(...) dapat dirangkai
bersama, dan bertindak sebagai ekspresi and(...). Misalnya, dua kueri berikut secara logis setara dan dapat digunakan secara bergantian.
Node.js
const results = await db.pipeline() .collection("books") .where(eq("rating", 5.0)) .where(lt('published', 1900)) .execute(); const results = await db.pipeline() .collection("books") .where(and( eq("rating", 5.0), lt('published', 1900))) .execute();
Web versi 9
let results; results = await execute(db.pipeline().collection("books") .where(field("rating").equal(5)) .where(field("published").lessThan(1900)) ); results = await execute(db.pipeline().collection("books") .where(and(field("rating").equal(5), field("published").lessThan(1900))) );
Swift
var results: Pipeline.Snapshot results = try await db.pipeline().collection("books") .where(Field("rating").equal(5)) .where(Field("published").lessThan(1900)) .execute() results = try await db.pipeline().collection("books") .where(Field("rating").equal(5) && Field("published").lessThan(1900)) .execute()
Kotlin
Android
var results: Task<Pipeline.Snapshot> results = db.pipeline().collection("books") .where(field("rating").equal(5)) .where(field("published").lessThan(1900)) .execute() results = db.pipeline().collection("books") .where(Expression.and(field("rating").equal(5), field("published").lessThan(1900))) .execute()
Java
Android
Task<Pipeline.Snapshot> results; results = db.pipeline().collection("books") .where(field("rating").equal(5)) .where(field("published").lessThan(1900)) .execute(); results = db.pipeline().collection("books") .where(Expression.and( field("rating").equal(5), field("published").lessThan(1900) )) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import And, Field results = ( client.pipeline() .collection("books") .where(Field.of("rating").equal(5)) .where(Field.of("published").less_than(1900)) .execute() ) results = ( client.pipeline() .collection("books") .where(And(Field.of("rating").equal(5), Field.of("published").less_than(1900))) .execute() )
Select/Add & Remove Fields
select(...),
add_fields(...), &
remove_fields(...) memungkinkan Anda mengubah
kolom yang ditampilkan dari tahap sebelumnya. Ketiga tahap ini umumnya
disebut sebagai tahap gaya proyeksi.
select(...) dan
add_fields(...) memungkinkan Anda menentukan
hasil ekspresi ke nama kolom yang disediakan pengguna. select(...) hanya akan menampilkan dokumen dengan nama kolom yang ditentukan, sedangkan add_fields(...) akan memperluas skema tahap sebelumnya (kemungkinan akan menimpa nilai dengan nama kolom yang mirip).
remove_fields(...) memungkinkan penentuan
sekumpulan kolom yang akan dihapus dari tahap sebelumnya. Tidak ada operasi yang dilakukan jika nama kolom yang ditentukan tidak ada.
Lihat bagian Membatasi Kolom yang Ditampilkan di bawah. Namun secara umum, penggunaan tahap tersebut untuk membatasi hasil hanya pada kolom yang diperlukan di klien akan membantu mengurangi biaya dan latensi untuk sebagian besar kueri.
Aggregate/Distinct
Tahap aggregate(...) memungkinkan Anda melakukan serangkaian
penggabungan pada dokumen input. Secara default, semua dokumen digabungkan, tetapi argumen grouping opsional dapat diberikan, sehingga dokumen input dapat digabungkan ke dalam bucket yang berbeda.
Node.js
const results = await db.pipeline() .collection("books") .aggregate({ accumulators: [avg('rating').as('avg_rating')], groups: ['genre'], }) .execute();
Web versi 9
const results = await execute(db.pipeline() .collection("books") .aggregate( field("rating").average().as("avg_rating") ) .distinct(field("genre")) );
Swift
let results = try await db.pipeline() .collection("books") .aggregate([ Field("rating").average().as("avg_rating") ], groups: [ Field("genre") ]) .execute()
Kotlin
Android
val results = db.pipeline() .collection("books") .aggregate( AggregateStage .withAccumulators(AggregateFunction.average("rating").alias("avg_rating")) .withGroups(field("genre")) ) .execute()
Java
Android
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .aggregate(AggregateStage .withAccumulators( AggregateFunction.average("rating").alias("avg_rating")) .withGroups(field("genre"))) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .aggregate( Field.of("rating").average().as_("avg_rating"), groups=[Field.of("genre")] ) .execute() )
Jika groupings tidak ditentukan, tahap ini hanya akan menghasilkan satu dokumen, atau dokumen akan dibuat untuk setiap kombinasi unik nilai groupings.
Tahap distinct(...) adalah operator
penggabungan yang disederhanakan yang memungkinkan pembuatan groupings unik secara khusus tanpa akumulator. Perilakunya mirip dengan
aggregate(...) dalam segala aspek lainnya. Contoh
berikut menunjukkan:
Node.js
const results = await db.pipeline() .collection("books") .distinct(toUppercase(Field.of("author")).as("author"), Field.of("genre")) .execute();
Web versi 9
const results = await execute(db.pipeline() .collection("books") .distinct( field("author").toUpper().as("author"), field("genre") ) );
Swift
let results = try await db.pipeline() .collection("books") .distinct([ Field("author").toUpper().as("author"), Field("genre") ]) .execute()
Kotlin
Android
val results = db.pipeline() .collection("books") .distinct( field("author").toUpper().alias("author"), field("genre") ) .execute()
Java
Android
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .distinct( field("author").toUpper().alias("author"), field("genre") ) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .distinct(Field.of("author").to_upper().as_("author"), "genre") .execute() )
Fungsi
Fungsi adalah elemen penyusun untuk membuat ekspresi dan kueri yang kompleks. Untuk mengetahui daftar lengkap fungsi beserta contohnya, lihat Referensi fungsi. Sebagai pengingat, pertimbangkan struktur kueri umum:

Banyak tahap menerima ekspresi yang berisi satu atau beberapa fungsi. Penggunaan fungsi yang paling umum akan ditemukan di tahap where(...) dan select(...). Ada dua jenis fungsi utama yang harus Anda ketahui:
Node.js
// Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. const results = await db.pipeline() .collection("books") .select(logicalMin(Field.of("current"),Field.of("updated")).as("price_min")) .execute(); // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. const results = await db.pipeline() .collection("books") .aggregate(min(Field.of("price"))) .execute();
Web versi 9
let results; // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = await execute(db.pipeline().collection("books") .select(field("current").logicalMinimum(field("updated")).as("price_min")) ); // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = await execute(db.pipeline().collection("books") .aggregate(field("price").minimum().as("min_price")) );
Swift
var results: Pipeline.Snapshot // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = try await db.pipeline().collection("books") .select([ Field("current").logicalMinimum(["updated"]).as("price_min") ]) .execute() // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = try await db.pipeline().collection("books") .aggregate([Field("price").minimum().as("min_price")]) .execute()
Kotlin
Android
var results: Task<Pipeline.Snapshot> // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = db.pipeline().collection("books") .select( field("current").logicalMinimum("updated").alias("price_min") ) .execute() // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = db.pipeline().collection("books") .aggregate(AggregateFunction.minimum("price").alias("min_price")) .execute()
Java
Android
Task<Pipeline.Snapshot> results; // Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results = db.pipeline().collection("books") .select( field("current").logicalMinimum("updated").alias("price_min") ) .execute(); // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results = db.pipeline().collection("books") .aggregate(AggregateFunction.minimum("price").alias("min_price")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field # Type 1: Scalar (for use in non-aggregation stages) # Example: Return the min store price for each book. results = ( client.pipeline() .collection("books") .select( Field.of("current").logical_minimum(Field.of("updated")).as_("price_min") ) .execute() ) # Type 2: Aggregation (for use in aggregate stages) # Example: Return the min price of all books. results = ( client.pipeline() .collection("books") .aggregate(Field.of("price").minimum().as_("min_price")) .execute() )
Batas
Pada umumnya, Edisi Enterprise tidak membatasi bentuk
kueri. Dengan kata lain, Anda tidak dibatasi untuk hanya menggunakan sejumlah kecil nilai dalam kueri IN atau OR. Namun, ada dua batasan utama yang harus Anda ketahui:
- Batas waktu: 60 detik (sama dengan Edisi Standard).
- Penggunaan Memori: Batas 128 MiB untuk jumlah data yang diwujudkan selama eksekusi kueri.
Error
Anda bisa saja mengalami kegagalan kueri karena sejumlah alasan. Berikut link ke error umum dan tindakan terkait yang dapat Anda lakukan:
| Kode Error | Tindakan |
DEADLINE_EXCEEDED
|
Kueri yang Anda jalankan melebihi batas waktu 60 detik dan memerlukan pengoptimalan tambahan. Lihat bagian performa untuk mendapatkan tips. Jika Anda tidak dapat menemukan akar masalahnya, silakan hubungi tim. |
RESOURCE_EXHAUSTED
|
Kueri yang Anda jalankan melebihi batas memori dan memerlukan pengoptimalan tambahan. Lihat bagian performa untuk mendapatkan tips. Jika Anda tidak dapat menemukan akar masalahnya, silakan hubungi tim. |
INTERNAL
|
Hubungi tim untuk mendapatkan dukungan. |
Performa
Database edisi Enterprise tidak selalu memerlukan indeks.
Artinya, kueri dapat menunjukkan latensi yang lebih tinggi dibandingkan dengan kueri yang sudah ada, yang akan langsung gagal dengan error indeks yang hilang FAILED_PRECONDITION. Untuk meningkatkan performa operasi Pipeline, ada beberapa langkah yang dapat Anda lakukan.
Membuat Indeks
Indeks yang Digunakan
Dengan Query Explain, Anda dapat mengetahui apakah kueri Anda ditayangkan oleh indeks atau dikembalikan ke operasi yang kurang efisien seperti pemindaian tabel. Jika kueri Anda tidak sepenuhnya ditayangkan dari indeks, Anda dapat membuat indeks dengan mengikuti petunjuk yang ada.
Membuat Indeks
Anda dapat mengikuti dokumentasi pengelolaan indeks yang ada untuk membuat indeks. Sebelum membuat indeks, pahami praktik terbaik umum terkait indeks di Firestore. Untuk memastikan kueri Anda dapat memanfaatkan indeks, ikuti praktik terbaik untuk membuat indeks dengan kolom dalam urutan berikut:
- Semua kolom yang akan digunakan dalam filter kesetaraan (dalam urutan apa pun)
- Semua kolom yang akan diurutkan (dalam urutan yang sama)
- Kolom yang akan digunakan dalam filter rentang atau ketidaksetaraan dalam urutan menurun dari selektivitas batasan kueri
Misalnya, untuk kueri berikut,
Node.js
const results = await db.pipeline() .collection('books') .where(lt('published', 1900)) .where(eq('genre', 'Science Fiction')) .where(gt('avg_rating', 4.3)) .sort(Field.of('published').descending()) .execute();
Web versi 9
const results = await execute(db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) );
Swift
let results = try await db.pipeline() .collection("books") .where(Field("published").lessThan(1900)) .where(Field("genre").equal("Science Fiction")) .where(Field("rating").greaterThan(4.3)) .sort([Field("published").descending()]) .execute()
Kotlin
Android
val results = db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) .execute()
Java
Android
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .where(field("published").lessThan(1900)) .where(field("genre").equal("Science Fiction")) .where(field("rating").greaterThan(4.3)) .sort(field("published").descending()) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .where(Field.of("published").less_than(1900)) .where(Field.of("genre").equal("Science Fiction")) .where(Field.of("rating").greater_than(4.3)) .sort(Field.of("published").descending()) .execute() )
Indeks yang direkomendasikan adalah indeks cakupan koleksi pada books untuk (genre [...], published DESC, avg_rating DESC).
Kepadatan indeks
Firestore mendukung indeks sparse dan non-sparse. Untuk mengetahui informasi selengkapnya, lihat Kepadatan indeks.
Kueri yang Tercakup + Indeks Sekunder
Firestore dapat melewati pengambilan dokumen lengkap dan hanya menampilkan hasil dari indeks jika semua kolom yang ditampilkan ada dalam indeks sekunder. Hal ini biasanya akan menghasilkan penurunan latensi (dan biaya) yang signifikan. Dengan contoh kueri di bawah:
Node.js
const results = await db.pipeline() .collection("books") .where(like(Field.of("category"), "%fantasy%")) .where(exists("title")) .where(exists("author")) .select("title", "author") .execute();
Web versi 9
const results = await execute(db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) );
Swift
let results = try await db.pipeline() .collection("books") .where(Field("category").like("%fantasy%")) .where(Field("title").exists()) .where(Field("author").exists()) .select([Field("title"), Field("author")]) .execute()
Kotlin
Android
val results = db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) .execute()
Java
Android
Task<Pipeline.Snapshot> results = db.pipeline() .collection("books") .where(field("category").like("%fantasy%")) .where(field("title").exists()) .where(field("author").exists()) .select(field("title"), field("author")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field results = ( client.pipeline() .collection("books") .where(Field.of("category").like("%fantasy%")) .where(Field.of("title").exists()) .where(Field.of("author").exists()) .select("title", "author") .execute() )
Jika database sudah memiliki indeks cakupan koleksi pada books untuk
(category [...], title [...], author [...]), database dapat menghindari pengambilan
apa pun dari dokumen utama itu sendiri. Dalam kasus ini, urutan dalam
indeks tidaklah penting, hal ini ditandai dengan [...].
Membatasi Kolom yang akan Ditampilkan
Secara default, kueri Firestore menampilkan semua kolom dalam dokumen, yang serupa dengan SELECT * dalam sistem relasional. Namun, jika aplikasi Anda hanya memerlukan sebagian kecil kolom, tahap select(...) atau restrict(...) dapat digunakan untuk mengirim pemfilteran ini ke sisi server. Hal ini akan mengurangi ukuran respons (mengurangi biaya egress jaringan) sekaligus mengurangi latensi.
Alat Pemecahan Masalah
Query Explain
Dengan Query Explain, Anda dapat memiliki visibilitas terkait metrik eksekusi dan detail tentang indeks yang digunakan.
Metrik
Operasi Pipeline terintegrasi sepenuhnya dengan metrik Firestore yang ada.
Masalah Umum/Batasan
Indeks Khusus
Operasi Pipeline belum mendukung jenis indeks array-contains & vector yang ada. Agar tidak terus-menerus menolak kueri tersebut, Firestore akan mencoba menggunakan indeks ascending & descending lainnya yang ada. Selama pratinjau pribadi, operasi Pipeline dengan ekspresi array_contains atau find_nearest tersebut diperkirakan akan lebih lambat daripada kueri yang setara karena hal ini.
Dukungan Real-time dan Offline
Operasi Pipeline tidak memiliki kemampuan real-time dan offline.
Langkah berikutnya
- Lihat Referensi fungsi.
- Pelajari cara Melakukan penggabungan dengan subkueri.