Distinct

Deskripsi

Mencari tahu nilai unik kolom atau ekspresi dari tahap sebelumnya.

Sintaksis

Tahap distinct memiliki sintaksis yang mirip dengan select. Diperlukan satu atau beberapa ekspresi yang dapat dipilih untuk memilih dan menemukan nilai unik. String dapat digunakan saat ekspresinya hanya berupa referensi kolom:

Node.js

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

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

Contoh klien

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

var cities = db.pipeline()
    .collection("cities")
    .distinct("country")
    .execute()

cities = db.pipeline()
    .collection("cities")
    .distinct(
        field("state").toLower().alias("normalizedState"),
        field("country")
    )
    .execute()

Java

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

Dari segi perilaku proyeksi, distinct mirip seperti select dengan penghapusan duplikat, sehingga ekspresi yang dapat dipilih yang tersedia untuk select juga dapat digunakan untuk distinct.

Tahap distinct berfungsi mirip dengan tahap aggregate tanpa grup.

Lihat juga Tahap Aggregate dan Tahap 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, 1L bilangan bulat 64-bit, dan 1.0 floating point, distinct hanya akan menampilkan 1 hasil.

Jika ada nilai setara yang berbeda dalam set data, nilai output grup 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.