背景
管道作業為 Cloud Firestore 提供新的查詢介面,支援進階查詢功能和複雜運算式。其中導入許多新函式,包括 min(...)、max(...)、substring(...)、regex_match(...) 和 array_contains_all(...),以及可執行複雜轉換的階段。
開始使用
如要安裝及初始化用戶端 SDK,請參閱下列指南中的操作說明:
語法
以下各節將概略說明管道作業的語法。
概念
與管道作業的一個顯著差異是引入了明確的「階段」排序。因此可以表達更複雜的查詢。不過,這與使用 Core 作業的現有查詢介面有明顯差異,後者會隱含階段順序。請參考以下管道作業範例:
Web
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
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
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) )
Go
pipeline := client.Pipeline(). Collection("cities"). Where(firestore.FieldOf("population").GreaterThan(100000)). Sort(firestore.Orders(firestore.Ascending(firestore.FieldOf("name")))). Limit(10)
初始化
管道作業的語法與現有 Cloud Firestore 查詢非常相似。首先,請編寫下列內容來初始化查詢:
Web
const { getFirestore } = require("firebase/firestore"); const { execute } = require("firebase/firestore/pipelines"); const database = getFirestore(app, "enterprise"); const pipeline = database.pipeline();
Swift
let firestore = Firestore.firestore(database: "enterprise") let pipeline = firestore.pipeline()
Kotlin
val firestore = Firebase.firestore("enterprise") val pipeline = firestore.pipeline()
Java
FirebaseFirestore firestore = FirebaseFirestore.getInstance("enterprise"); PipelineSource pipeline = firestore.pipeline();
Python
firestore_client = firestore.client(default_app, "your-new-enterprise-database") pipeline = firestore_client.pipeline()
Go
client, err := firestore.NewClientWithDatabase(ctx, projectID, databaseID) if err != nil { fmt.Fprintf(w, "firestore.NewClientWithDatabase failed: %v", err) return err } defer client.Close() pipeline := client.Pipeline().Collection("books")
結構
建立管道作業時,請務必瞭解幾個重要詞彙:階段、運算式、函式和子查詢包裝函式。

階段:管道可能包含一或多個階段。在邏輯上,這些代表執行查詢時採取的一系列步驟 (或階段)。
運算式:階段通常會接受運算式,讓您表達更複雜的查詢。運算式可能很簡單,由單一函式組成,例如 eq("a", 1)。您也可以透過巢狀結構運算式 (例如 and(eq("a", 1), eq("b", 2)).) 表達更複雜的運算式
子查詢包裝函式:array() 和 scalar() 等函式可讓您將巢狀管道嵌入為階段中的運算式。
欄位 / 常數 / 變數
管道作業支援複雜運算式。因此,請務必區分值代表的是「欄位」、「常數」還是「變數」。
「欄位」是指文件中的資料,「常數」可將任何值指定為運算式的引數,「變數」則可定義及使用暫時值,其範圍限於查詢執行作業,而非處理中的文件。以下提供這些概念的總覽,如要進一步瞭解如何在查詢執行期間讀取和寫入變數,請參閱 let(...) 階段。
| 欄位 | 常數 | 變數 | |
|---|---|---|---|
| Purpose | 存取或儲存文件中的欄位 | 指定固定值 | 在管道執行期間使用暫時值 |
| SDK 使用情形 | field("name") |
constant("val") |
variable("name") |
| 範圍 | 目前文件的本機 | 全球 | 全域 (適用於管道和子管道) |
| 未定義的參照 | 評估結果為 absent |
不適用 | 產生執行階段錯誤 |
範例:
Web
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
val pipeline = db.pipeline() .collection("cities") .where(field("name").equal(constant("Toronto")))
Java
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"))) )
Go
pipeline := client.Pipeline().Collection("cities"). Where(firestore.FieldOf("name").Equal(firestore.ConstantOf("Toronto")))
階段
輸入階段
輸入階段代表查詢的第一個階段。定義要查詢的初始文件集。就管道作業而言,這與現有查詢大致相似,大多數查詢都是以 collection(...) 或 collection_group(...) 階段開頭。兩個新的輸入階段為 database() 和 documents(...),其中 database() 允許傳回資料庫中的「所有」文件,而 documents(...) 的作用與批次讀取相同。
Web
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
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
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() )
Go
// Return all restaurants in San Francisco results1, err := client.Pipeline().Collection("cities/sf/restaurants").Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Return all restaurants results2, err := client.Pipeline().CollectionGroup("restaurants").Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Return all documents across all collections in the database (the entire database) results3, err := client.Pipeline().Database().Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Batch read of 3 documents results4, err := client.Pipeline(). Documents([]*firestore.DocumentRef{ client.Collection("cities").Doc("SF"), client.Collection("cities").Doc("DC"), client.Collection("cities").Doc("NY"), }). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err }
與所有其他階段一樣,這些輸入階段的結果順序並不穩定。如果需要特定排序,請務必加入 sort(...) 運算子。
其中
where(...) 階段會對前一階段產生的文件執行標準篩選作業,且大多會反映現有查詢的「where」語法。如果指定運算式評估結果為非 true 值,系統會從傳回的文件中篩除該文件。
多個 where(...) 陳述式可以鏈結在一起,並做為 and(...) 運算式。舉例來說,以下兩個查詢在邏輯上等效,可以交替使用。
Web
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
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
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() )
Go
results1, err := client.Pipeline(). Collection("books"). Where(firestore.FieldOf("rating").Equal(5)). Where(firestore.FieldOf("published").LessThan(1900)). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } results2, err := client.Pipeline(). Collection("books"). Where(firestore.And( firestore.FieldOf("rating").Equal(5), firestore.FieldOf("published").LessThan(1900), )). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err }
選取 / 新增及移除欄位
select(...)、add_fields(...) 和 remove_fields(...) 都能讓您修改前一個階段傳回的欄位。這三種通常稱為投影式舞台。
select(...) 和 add_fields(...) 可讓您將運算式的結果指定給使用者提供的欄位名稱。select(...) 只會傳回具有指定欄位名稱的文件,而 add_fields(...) 則會擴充前一階段的結構定義 (可能會覆寫具有相同欄位名稱的值)。
remove_fields(...) 可指定要從上一個階段移除的一組欄位。指定不存在的欄位名稱不會執行任何操作。
請參閱下方的「限制要傳回的欄位」一節,但一般來說,使用這類階段將結果限制為僅限用戶端所需的欄位,有助於降低大多數查詢的成本和延遲時間。
匯總 / 不重複
aggregate(...) 階段可讓您對輸入文件執行一系列匯總。根據預設,所有文件都會匯總在一起,但您可以提供選用的 grouping 引數,將輸入文件匯總到不同的值區。
Web
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
val results = db.pipeline() .collection("books") .aggregate( AggregateStage .withAccumulators(AggregateFunction.average("rating").alias("avg_rating")) .withGroups(field("genre")) ) .execute()
Java
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() )
Go
snapshot := client.Pipeline(). Collection("books"). Aggregate( firestore.Accumulators(firestore.Average("rating").As("avg_rating")), firestore.WithAggregateGroups("genre"), ). Execute(ctx)
如未指定 groupings,這個階段只會產生一份文件,否則會為每個不重複的 groupings 值組合產生一份文件。
distinct(...) 階段是簡化的匯總運算子,可產生不重複的 groupings,不需任何累加器。在其他方面,其行為與 aggregate(...) 完全相同。以下範例說明:
Web
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
val results = db.pipeline() .collection("books") .distinct( field("author").toUpper().alias("author"), field("genre") ) .execute()
Java
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() )
Go
snapshot := client.Pipeline(). Collection("books"). Distinct(firestore.Fields( firestore.ToUpper(firestore.FieldOf("author")).As("author"), firestore.FieldOf("genre"), )). Execute(ctx)
函式
函式是建立運算式和複雜查詢的基本要素。如需完整的函式清單和範例,請參閱函式參考資料。快速複習一下,一般查詢的結構如下:

許多階段都接受包含一或多個函式的運算式。最常見的函式用途會出現在 where(...) 和 select(...) 階段。您應熟悉兩種主要函式:
Web
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
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
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() )
Go
// Type 1: Scalar (for use in non-aggregation stages) // Example: Return the min store price for each book. results1, err := client.Pipeline(). Collection("books"). Select(firestore.Fields( firestore.LogicalMinimum(firestore.FieldOf("current"), firestore.FieldOf("updated")).As("price_min"), )). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Type 2: Aggregation (for use in aggregate stages) // Example: Return the min price of all books. results2, err := client.Pipeline(). Collection("books"). Aggregate(firestore.Accumulators( firestore.Minimum("price").As("min_price"), )). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err }
限制
在大多數情況下,Enterprise 版不會對查詢形式施加限制。換句話說,您在 IN 或 OR 查詢中不限於少數值。不過,您應留意以下兩項主要限制:
- 期限:60 秒 (與 Standard 版本相同)。
- 記憶體用量:查詢執行期間,具體化資料量上限為 128 MiB。
錯誤
查詢失敗的原因有很多。請參閱常見錯誤和相關因應措施:
| 錯誤代碼 | 動作 |
DEADLINE_EXCEEDED
|
您執行的查詢超過 60 秒的期限,需要進一步最佳化。如需相關提示,請參閱「成效」一節。如果無法找出問題的根本原因,請與團隊聯絡。 |
RESOURCE_EXHAUSTED
|
您執行的查詢超出記憶體限制,需要進一步最佳化。如需相關提示,請參閱「成效」一節。如果無法找出問題的根本原因,請與團隊聯絡。 |
INTERNAL
|
聯絡團隊尋求支援。 |
效能
Enterprise 版資料庫不一定要有索引。這表示與現有查詢相比,查詢可能會出現較高的延遲時間,而現有查詢只會立即失敗,並顯示 FAILED_PRECONDITION 缺少索引錯誤。如要提升管道作業的效能,可以採取下列步驟。
建立索引
使用的索引
查詢說明可讓您判斷查詢是由索引提供,還是改用效率較低的操作 (例如資料表掃描)。如果查詢未完全由索引提供,請按照操作說明建立索引。
建立索引
您可以按照現有的索引管理說明文件建立索引。建立索引前,請先熟悉 Cloud Firestore 中索引的一般最佳做法。為確保查詢能使用索引,請按照最佳做法,依下列順序建立含有欄位的索引:
- 所有會用於等式篩選器的欄位 (不限順序)
- 所有要排序的欄位 (順序相同)
- 將用於範圍或不等式篩選器的欄位,依查詢限制選擇性遞減排序
舉例來說,以下查詢
Web
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
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
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() )
Go
snapshot := client.Pipeline(). Collection("books"). Where(firestore.FieldOf("published").LessThan(1900)). Where(firestore.FieldOf("genre").Equal("Science Fiction")). Where(firestore.FieldOf("rating").GreaterThan(4.3)). Sort(firestore.Orders(firestore.Descending(firestore.FieldOf("published")))). Execute(ctx)
建議的索引是 (genre [...], published DESC, avg_rating DESC). 的 books 集合範圍索引
索引密度
Cloud Firestore 支援稀疏和非稀疏索引。詳情請參閱「索引密度」。
涵蓋查詢 + 次要索引
如果傳回的所有欄位都存在於次要索引中,Cloud Firestore 就能略過擷取完整文件的步驟,直接從索引傳回結果。這通常能大幅改善延遲時間和成本。使用下列查詢範例:
Web
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
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
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() )
Go
snapshot := client.Pipeline(). Collection("books"). Where(firestore.FieldOf("category").Like("%fantasy%")). Where(firestore.FieldOf("title").FieldExists()). Where(firestore.FieldOf("author").FieldExists()). Select(firestore.Fields("title", "author")). Execute(ctx)
如果資料庫已有 (category [...], title [...], author [...]) 的 books 集合範圍索引,則可避免從主要文件本身擷取任何內容。在這種情況下,索引中的順序並不重要,[...] 是用來表示這一點。
限制要傳回的欄位
根據預設,Cloud Firestore 查詢會傳回文件中的所有欄位,類似於關聯系統中的 SELECT *。不過,如果應用程式只需要部分欄位,可以使用 select(...) 或 restrict(...) 階段,將這項篩選作業推送至伺服器端。這樣做可縮減回應大小 (降低網路輸出費用),並縮短延遲時間。
疑難排解工具
查詢說明
查詢說明功能可讓您查看執行指標和所用索引的詳細資料。
指標
管道作業與現有的 Cloud Firestore 指標完全整合。
已知問題 / 限制
特殊索引
管道作業尚不支援現有的 array-contains 和 vector 索引類型。Cloud Firestore 不會直接拒絕這類查詢,而是會嘗試使用其他現有的 ascending 和 descending 索引。因此,使用這類 array_contains 或 find_nearest 運算式的速度,預計會比現有對等運算式慢。
即時和離線支援
管道作業不具備即時和離線功能。
後續步驟
- 開始探索函式和階段參考文件。
- 瞭解如何使用子查詢執行 join。