Distinct (轉換階段)
說明
找出一系列運算式的所有不重複值組合。
distinct(...) 階段的語法與 select(...) 類似,因為它會採用一或多個可選取的運算式。如果運算式只是欄位參照,則可以使用字串:
範例
Node.js
let cities = await db.pipeline() .collection("cities") .distinct("country") .execute(); cities = await db.pipeline() .collection("cities") .distinct( field("state").toLower().as("normalizedState"), field("country")) .execute();
網頁
let cities = await execute(db.pipeline() .collection("cities") .distinct("country")); cities = await execute(db.pipeline() .collection("cities") .distinct( field("state").toLower().as("normalizedState"), field("country")));
Swift
let results = try await db.pipeline() .collection("books") .distinct([ Field("author").toUpper().as("author"), Field("genre") ]) .execute()
Kotlin
Android
var cities = db.pipeline() .collection("cities") .distinct("country") .execute() cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country") ) .execute()
Java
Android
Task<Pipeline.Snapshot> cities; cities = db.pipeline() .collection("cities") .distinct("country") .execute(); cities = db.pipeline() .collection("cities") .distinct( field("state").toLower().alias("normalizedState"), field("country")) .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Field cities = client.pipeline().collection("cities").distinct("country").execute() cities = ( client.pipeline() .collection("cities") .distinct(Field.of("state").to_lower().as_("normalizedState"), "country") .execute() )
Java
Pipeline.Snapshot cities1 = firestore.pipeline().collection("cities").distinct("country").execute().get(); Pipeline.Snapshot cities2 = firestore .pipeline() .collection("cities") .distinct(toLower(field("state")).as("normalizedState"), field("country")) .execute() .get();
行為
distinct(...) 階段的運作方式與沒有群組的 aggregate(...) 階段類似。另請參閱 aggregate(...) 和 select(...)。
尋找不重複的欄位值
舉例來說,如要取得下列cities集合中的所有國家/地區清單:
Node.js
await db.collection("cities").doc("SF").set({name: "San Francisco", state: "CA", country: "USA"});
await db.collection("cities").doc("LA").set({name: "Los Angeles", state: "CA", country: "USA"});
await db.collection("cities").doc("NY").set({name: "New York", state: "NY", country: "USA"});
await db.collection("cities").doc("TOR").set({name: "Toronto", state: null, country: "Canada"});
await db.collection("cities").doc("MEX").set({name: "Mexico City", state: null, country: "Mexico"});
您可以使用下列方式找出不同國家/地區:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct("country")
.execute();
這會產生下列結果:
{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }
運算式的不同輸出內容
您也可以找出多個欄位的不同組合,或更複雜的運算式。例如:
Node.js
const cities = await db.pipeline()
.collection("/cities")
.distinct(
field("state").toLower().as("normalized_state"),
field("country"))
.execute();
取得:
{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }
等價行為
不同值的等價行為與等價行為的語意相同。
也就是說,無論原始型別 (32 位元整數、64 位元整數、浮點數、十進位數字等),數學上相等的數值都會視為相同的不重複值。
舉例來說,在集合 numerics 中,不同文件分別包含 32 位元整數 1、64 位元整數 1L 和浮點數 1.0 的 foo 值,distinct(...) 只會傳回 1 個結果。
如果資料集中存在不同的等效值,群組的輸出值可以是任何一個等效值。在本範例中,foo 的值可能會以 1、1L 或 1.0 的形式傳回。
即使看起來是決定性行為,您也不應嘗試依賴選取特定值的行為。
記憶體用量
distinct(...) 階段的執行方式取決於可用的索引。如果查詢最佳化工具未選擇適當的索引,distinct(...) 就需要將所有不重複的值緩衝處理至記憶體。
如果相異值數量非常龐大,或值本身非常大 (例如相異值很大),這個階段可能會耗盡記憶體。
在這種情況下,您應套用篩選器來限制資料集,以執行 distinct(...),或按照建議建立索引,避免大量使用記憶體。
查詢說明功能會提供實際查詢執行計畫和剖析資料,協助您進行偵錯。