Ringkasan kueri dengan filter rentang dan ketidaksetaraan di beberapa kolom

Firestore mendukung penggunaan filter rentang dan ketidaksetaraan di beberapa kolom dalam satu kueri. Anda dapat memiliki kondisi rentang dan ketidaksetaraan di beberapa kolom dan menyederhanakan pengembangan aplikasi dengan mendelegasikan implementasi logika pasca-pemfilteran ke Firestore.

Filter rentang dan ketidaksetaraan di beberapa kolom

Kueri berikut menggunakan filter rentang pada populasi dan kepadatan untuk menampilkan semua kota dengan jumlah penduduk lebih dari 1.000.000 orang dan kepadatan penduduk kurang dari 10.000 orang per unit area.

Modular web versi 9

const q = query(
    collection(db, "cities"),
    where('population', '>', 1000000),
    where('density', '<', 10000),
  );

Swift

let query = db.collection("cities")
  .whereField("population", isGreaterThan: 1000000)
  .whereField("density", isLessThan: 10000)

Objective-C

FIRQuery *query =
 [[[[self.db collectionWithPath:@"cities"]
queryWhereField:@"population" isGreaterThan:@1000000]
   queryWhereField:@"density" isLessThan:@10000];

Java Android

Query query = db.collection("cities")
 .whereGreaterThan("population", 1000000)
 .whereLessThan("density", 10000);

Kotlin+KTX Android

val query = db.collection("cities")
 .whereGreaterThan("population", 1000000)
 .whereLessThan("density", 10000)

Go

   query := client.Collection("cities").
      Where("population", ">", 1000000).
      Where("density", "<", 10000)

Java

db.collection("cities")
  .whereGreaterThan("population", 1000000)
  .whereLessThan("density", 10000);

Node.js

db.collection("cities")
  .where('population', '>', 1000000),
  .where('density', '<', 10000)

Python

from google.cloud import firestore

db = firestore.Client()
query = db.collection("cities")
.where("population", ">", 1000000)
.where("density", "<", 10000)

PHP

$collection = $db->collection('samples/php/cities');
$chainedQuery = $collection
    ->where('population', '>', 1000000)
    ->where('density', '<', 10000);

C#

CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef
    .WhereGreaterThan("Population", 1000000)
    .WhereLessThan("Density", 10000);
QuerySnapshot querySnapshot = await query.GetSnapshotAsync();
foreach (DocumentSnapshot documentSnapshot in querySnapshot)
{
    var name = documentSnapshot.GetValue<string>("Name");
    var population = documentSnapshot.GetValue<int>("Population");
    var density = documentSnapshot.GetValue<int>("Density");
    Console.WriteLine($"City '{name}' returned by query. Population={population}; Density={density}");
}

Ruby

query = cities_ref.where("population", ">", "1000000")
                  .where("density", "<", 10000)

C++

CollectionReference cities_ref = db->Collection("cities");
Query query = cities_ref.WhereGreaterThan("population", FieldValue::Integer(1000000))
                       .WhereLessThan("density", FieldValue::Integer(10000));

Unity

CollectionReference citiesRef = db.Collection("cities");
Query query = citiesRef.WhereGreaterThan("population", 1000000)
                      .WhereLessThan("density", 10000);

Dart

final citiesRef = FirebaseFirestore.instance.collection('cities')
final query = citiesRef.where("population", isGreaterThan: 1000000)
                  .where("density", isLessThan: 10000);

Pertimbangan pengindeksan

Sebelum menjalankan kueri, baca tentang kueri dan model data Firestore.

Di Firestore, klausa ORDER BY dari kueri menentukan indeks mana yang dapat digunakan untuk menyajikan kueri. Misalnya, kueri ORDER BY a ASC, b ASC memerlukan indeks komposit pada kolom a ASC, b ASC.

Untuk mengoptimalkan performa dan biaya kueri Firestore, optimalkan urutan kolom dalam indeks. Untuk melakukannya, pastikan indeks diurutkan dari kiri ke kanan sehingga kueri disaring ke set data yang mencegah pemindaian entri indeks yang tidak relevan.

Misalkan Anda ingin menelusuri kumpulan karyawan untuk menemukan karyawan Amerika Serikat yang gajinya lebih dari $100.000 dan jumlah tahun pengalamannya lebih besar dari 0. Berdasarkan pemahaman Anda terhadap set data, Anda tahu bahwa batasan gaji lebih selektif daripada batasan pengalaman. Indeks ideal yang dapat mengurangi jumlah pemindaian indeks adalah (salary [...], experience [...]). Dengan demikian, kueri yang akan cepat dan hemat biaya akan mengurutkan salary sebelum experience dan terlihat seperti berikut:

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .whereGreaterThan("experience", 0)
  .orderBy("salary")
  .orderBy("experience");

Node.js

db.collection("employees")
  .where("salary", ">", 100000)
  .where("experience", ">", 0)
  .orderBy("salary")
  .orderBy("experience");

Python

db.collection("employees")
  .where("salary", ">", 100000)
  .where("experience", ">", 0)
  .order_by("salary")
  .order_by("experience");

Praktik terbaik untuk mengoptimalkan indeks

Saat mengoptimalkan indeks, perhatikan praktik terbaik berikut.

Mengurutkan kolom indeks berdasarkan kesetaraan diikuti dengan sebagian besar kolom rentang atau ketidaksetaraan selektif

Firestore menggunakan kolom paling kiri pada indeks komposit untuk memenuhi batasan kesetaraan dan batasan rentang atau ketidaksetaraan, jika ada, di kolom pertama dari kueri orderBy(). Batasan ini dapat mengurangi jumlah entri indeks yang dipindai Firestore. Firestore menggunakan kolom yang tersisa dari indeks untuk memenuhi batasan rentang atau ketidaksetaraan lain dari kueri. Batasan ini tidak mengurangi jumlah entri indeks yang dipindai Firestore, tetapi memfilter dokumen yang tidak cocok sehingga jumlah dokumen yang ditampilkan kepada klien akan berkurang.

Untuk mengetahui informasi selengkapnya tentang cara membuat indeks yang efisien, lihat properti indeks.

Mengurutkan kolom dalam urutan menurun dari selektivitas batasan kueri

Untuk memastikan Firestore memilih indeks yang optimal untuk kueri Anda, tentukan klausa orderBy() yang mengurutkan kolom dalam urutan menurun dari selektivitas batasan kueri. Selektivitas yang lebih tinggi cocok dengan subset dokumen yang lebih kecil, sementara selektivitas yang lebih rendah sesuai dengan subset dokumen yang lebih besar. Pastikan bahwa Anda memilih kolom rentang atau ketidaksetaraan dengan selektivitas lebih tinggi sebelumnya di pengurutan indeks daripada kolom dengan selektivitas yang lebih rendah.

Untuk meminimalkan jumlah dokumen yang dipindai dan ditampilkan oleh Firestore melalui jaringan, Anda harus selalu mengurutkan kolom dalam urutan menurun dari selektivitas batasan kueri. Jika set hasil tidak dalam urutan yang diperlukan dan set hasil tersebut diharapkan kecil, Anda bisa menerapkan logika sisi klien untuk mengurutkan ulang sesuai ekspektasi pengurutan Anda.

Misalnya, Anda ingin menelusuri kumpulan karyawan untuk menemukan karyawan Amerika Serikat yang gajinya lebih dari $100.000 dan mengurutkan hasilnya berdasarkan tahun pengalaman karyawan. Jika Anda memperkirakan hanya sejumlah kecil karyawan yang menerima gaji lebih dari $100.000, maka cara paling efisien untuk menulis kueri adalah sebagai berikut:

Java

db.collection("employees")
  .whereGreaterThan("salary", 100000)
  .orderBy("salary")
  .get()
  .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
          // Order results by `experience`
        }
    });;

Node.js

const querySnapshot = await db.collection('employees')
                              .where("salary", ">", 100000)
                              .orderBy("salary")
                              .get();

// Order results by `experience`

Python

results = db.collection("employees")
            .where("salary", ">", 100000)
            .order_by("salary")
            .stream()

// Order results by `experience`

Meskipun menambahkan pengurutan pada experience ke kueri akan menghasilkan set dokumen yang sama dan meniadakan pengaturan ulang hasil pada klien, kueri mungkin membaca banyak entri indeks yang lebih tidak relevan daripada kueri sebelumnya. Hal ini karena Firestore selalu memilih indeks yang awalan kolom indeksnya cocok dengan urutan berdasarkan klausa kueri. Jika experience ditambahkan ke urutan berdasarkan klausa, Firestore akan memilih indeks (experience [...], salary [...]) untuk menghitung hasil kueri. Karena tidak ada batasan lain pada experience, Firestore akan membaca semua entri indeks koleksi employees sebelum menerapkan filter salary untuk menemukan set hasil akhirnya. Ini berarti entri indeks yang tidak memenuhi filter salary akan tetap dibaca, sehingga meningkatkan latensi dan biaya kueri.

Harga

Kueri dengan filter rentang dan ketidaksetaraan di beberapa kolom ditagih berdasarkan dokumen yang dibaca dan entri indeks yang dibaca.

Untuk mengetahui informasi mendetail, lihat halaman Harga.

Batasan

Selain batasan kueri, perhatikan batasan berikut sebelum menggunakan kueri dengan filter rentang dan ketidaksetaraan di beberapa kolom:

  • Kueri dengan filter rentang atau ketidaksetaraan di kolom dokumen dan hanya batasan kesetaraan pada kunci dokumen (__name__) tidak didukung.
  • Firestore membatasi jumlah kolom rentang atau ketidaksetaraan hingga 10. Cara ini untuk mencegah kueri menjadi terlalu mahal untuk dijalankan.

Langkah berikutnya