Berbeda (Tahap Transformasi)

Deskripsi

Temukan semua kombinasi nilai yang berbeda untuk serangkaian ekspresi.

Tahap distinct(...) memiliki sintaksis yang mirip dengan select(...) karena mengambil satu atau beberapa ekspresi yang dapat dipilih. String dapat digunakan saat ekspresinya hanya berupa referensi kolom:

Contoh

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();

Web

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();

Perilaku

Tahap distinct(...) berfungsi mirip dengan tahap aggregate(...) tanpa grup. Lihat juga aggregate(...) dan select(...).

Menemukan Nilai Kolom Unik

Misalnya, untuk mendapatkan daftar setiap negara dalam koleksi cities berikut:

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"});

Negara yang berbeda dapat ditemukan menggunakan:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .distinct("country")
  .execute();

yang hasilnya adalah sebagai berikut:

{ country: "USA" }
{ country: "Canada" }
{ country: "Mexico" }

Output Ekspresi Unik

Anda juga dapat menemukan kombinasi unik dari beberapa kolom, atau ekspresi yang lebih rumit. Contoh:

Node.js

const cities = await db.pipeline()
  .collection("/cities")
  .distinct(
    field("state").toLower().as("normalized_state"),
    field("country"))
  .execute();

untuk mendapatkan:

{ country: "USA", normalized_state: "ca" }
{ country: "USA", normalized_state: "ny" }
{ country: "Canada", normalized_state: null }
{ country: "Mexico", normalized_state: null }

Perilaku Setara

Perilaku setara pada nilai unik menggunakan semantik yang sama dengan kesetaraan.

Artinya, nilai yang setara, misalnya nilai numerik yang secara matematis setara, terlepas dari jenis aslinya (bilangan bulat 32-bit, bilangan bulat 64-bit, bilangan floating point, bilangan desimal, dll.), akan dianggap sebagai nilai unik yang sama.

Sebagai contoh, dalam koleksi numerics dengan berbagai dokumen yang masing-masing berisi nilai foo bilangan bulat 32-bit 1, bilangan bulat 64-bit 1L, dan floating point 1.0, distinct(...) hanya akan menampilkan 1 hasil.

Jika ada nilai setara yang berbeda dalam set data, nilai output kelompok dapat berupa salah satu dari nilai setara tersebut. Dalam contoh ini, nilai foo dapat ditampilkan sebagai 1, 1L, atau 1.0.

Meskipun tampak deterministik, Anda tidak boleh mencoba mengandalkan perilaku satu nilai spesifik yang dipilih.

Pemakaian Memori

Cara tahap distinct(...) dieksekusi bergantung pada indeks yang tersedia. Jika tidak ada indeks yang sesuai yang dipilih oleh pengoptimal kueri, distinct(...) harus melakukan buffering untuk semua nilai unik dalam memori.

Jika ada nilai unik dalam jumlah besar, atau nilai yang sangat besar (misalnya, unik dalam nilai yang sangat besar), tahap ini bisa saja kehabisan memori.

Dalam kasus seperti ini, sebaiknya terapkan filter untuk membatasi set data tempat Anda akan menjalankan tahap distinct(...), atau buat indeks sesuai rekomendasi untuk menghindari penggunaan memori yang besar.

Query Explain akan memberikan informasi tentang rencana eksekusi kueri yang sebenarnya dan data profiling untuk membantu proses debug.