Przegląd zapytań z filtrami zakresów i nierówności w wielu polach

Cloud Firestore umożliwia używanie filtrów zakresu i nierówności w wielu polach w jednym zapytaniu. Możesz stosować warunki zakresu i nierówności w przypadku wielu pól oraz uprościć tworzenie aplikacji, delegując implementację logiki filtrowania końcowego do Cloud Firestore.

Filtry zakresu i nierówności w wielu polach

To zapytanie używa filtrów zakresu dotyczących populacji i gęstości zaludnienia,aby zwrócić wszystkie miasta,w których populacja jest większa niż 1 000 000 osób,a gęstość zaludnienia jest mniejsza niż 10 000 osób na jednostkę powierzchni.

Wersja internetowa 9 (modułowa)

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

Uwagi dotyczące indeksowania

Zanim uruchomisz zapytania, przeczytaj informacje o zapytaniachCloud Firestore modelu danych.

Cloud Firestore klauzula ORDER BY zapytania określa, które indeksy mogą być używane do obsługi zapytania. Na przykład zapytanie ORDER BY a ASC, b ASC wymaga indeksu złożonego w polach a ASC, b ASC.

Aby zoptymalizować wydajność i koszty zapytań Cloud Firestore, zoptymalizuj kolejność pól w indeksie. Aby to zrobić, upewnij się, że indeks jest uporządkowany od lewej do prawej, tak aby zapytanie ograniczało się do zbioru danych, który uniemożliwia skanowanie niepotrzebnych wpisów indeksu.

Załóżmy, że chcesz przeszukać zbiór pracowników i znaleźć pracowników ze Stanów Zjednoczonych, których wynagrodzenie przekracza 100 tys. USD, a liczba lat doświadczenia jest większa niż 0. Na podstawie swojej wiedzy o zbiorze danych wiesz, że ograniczenie dotyczące wynagrodzenia jest bardziej selektywne niż ograniczenie dotyczące doświadczenia. Idealny indeks, który zmniejszyłby liczbę skanów indeksu, to (salary [...], experience [...]). Dlatego zapytanie, które będzie szybkie i opłacalne, będzie zawierać salary przed experience i będzie wyglądać tak:

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

Sprawdzone metody optymalizacji indeksów

Podczas optymalizacji indeksów pamiętaj o tych sprawdzonych metodach.

Uporządkuj pola indeksu według równości, a następnie według najbardziej selektywnego zakresu lub pola nierówności.

Cloud Firestore używa pól najbardziej po lewej stronie indeksu złożonego, aby spełnić ograniczenia równości oraz ograniczenia zakresu lub nierówności (jeśli takie istnieją) w pierwszym polu zapytania orderBy(). Te ograniczenia mogą zmniejszyć liczbę pozycji indeksu skanowanych przez Cloud Firestore. Cloud Firestore używa pozostałych pól indeksu, aby spełnić inne ograniczenia zakresu lub nierówności zapytania. Te ograniczenia nie zmniejszają liczby wpisów indeksu, które skanuje Cloud Firestore, ale odfiltrowują niedopasowane dokumenty, dzięki czemu zmniejsza się liczba dokumentów zwracanych klientom.

Więcej informacji o tworzeniu wydajnych indeksów znajdziesz w artykule Właściwości indeksu.

Uporządkuj pola w kolejności malejącej selektywności ograniczenia zapytania.

Aby mieć pewność, że Cloud Firestore wybierze optymalny indeks dla Twojego zapytania, określ klauzulę orderBy(), która porządkuje pola w kolejności malejącej selektywności ograniczeń zapytania. Większa selektywność dopasowuje mniejszy podzbiór dokumentów, a mniejsza selektywność dopasowuje większy podzbiór dokumentów. Upewnij się, że pola zakresu lub nierówności o wyższej selektywności są wybierane wcześniej w kolejności indeksu niż pola o niższej selektywności.

Aby zminimalizować liczbę dokumentów, które Cloud Firestore skanuje i zwraca w sieci, zawsze sortuj pola w kolejności malejącej selektywności ograniczeń zapytania. Jeśli zestaw wyników nie jest w wymaganej kolejności i oczekuje się, że będzie mały, możesz zaimplementować logikę po stronie klienta, aby zmienić jego kolejność zgodnie z oczekiwaniami.

Załóżmy na przykład, że chcesz przeszukać zbiór pracowników, aby znaleźć pracowników ze Stanów Zjednoczonych, których wynagrodzenie przekracza 100 tys. USD, i posortować wyniki według lat doświadczenia pracownika. Jeśli spodziewasz się,że tylko niewielka liczba pracowników będzie zarabiać więcej niż 100 000 USD, najskuteczniejszy sposób na napisanie zapytania jest następujący:

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`

Dodanie do zapytania klauzuli ORDER BY experience spowoduje zwrócenie tego samego zestawu dokumentów i wyeliminuje konieczność ponownego sortowania wyników na klientach, ale zapytanie może odczytać znacznie więcej zbędnych wpisów indeksu niż poprzednie zapytanie. Dzieje się tak, ponieważ Cloud Firestore zawsze preferuje indeks, którego pola indeksu mają prefiks pasujący do klauzuli order by zapytania. Jeśli do klauzuli ORDER BY dodano experience,Cloud Firestore wybierze indeks (experience [...], salary [...]) do obliczania wyników zapytania. Ponieważ nie ma innych ograniczeń dotyczących experience, usługa Cloud Firestore odczyta wszystkie wpisy indeksu kolekcji employees przed zastosowaniem filtra salary w celu znalezienia ostatecznego zestawu wyników. Oznacza to, że wpisy indeksu, które nie spełniają warunków filtra salary, są nadal odczytywane, co zwiększa czas oczekiwania na odpowiedź na zapytanie i jego koszt.

Ceny

Zapytania z filtrami zakresu i nierówności w wielu polach są rozliczane na podstawie odczytanych dokumentów i odczytanych wpisów indeksu.

Szczegółowe informacje znajdziesz na stronie Cennik.

Ograniczenia

Oprócz ograniczeń zapytań przed użyciem zapytań z filtrami zakresu i nierówności w wielu polach zwróć uwagę na te ograniczenia:

  • Zapytania z filtrami zakresu lub nierówności w polach dokumentu i tylko ograniczeniami równości w kluczu dokumentu (__name__) nie są obsługiwane.
  • Cloud Firestore ogranicza liczbę pól zakresu lub nierówności do 10. Ma to zapobiec zbyt wysokim kosztom uruchamiania zapytań.

Co dalej?