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.0foo 值,distinct(...) 只會傳回 1 個結果。

如果資料集中存在不同的等效值,群組的輸出值可以是任何一個等效值。在本範例中,foo 的值可能會以 11L1.0 的形式傳回。

即使看起來是決定性行為,您也不應嘗試依賴選取特定值的行為。

記憶體用量

distinct(...) 階段的執行方式取決於可用的索引。如果查詢最佳化工具未選擇適當的索引,distinct(...) 就需要將所有不重複的值緩衝處理至記憶體。

如果相異值數量非常龐大,或值本身非常大 (例如相異值很大),這個階段可能會耗盡記憶體。

在這種情況下,您應套用篩選器來限制資料集,以執行 distinct(...),或按照建議建立索引,避免大量使用記憶體。

查詢說明功能會提供實際查詢執行計畫和剖析資料,協助您進行偵錯。