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

Cloud Firestore obsługuje 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 wielu polach 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 w polach population i density,aby zwrócić wszystkie miasta,w których liczba mieszkańców jest większa niż 1 000 000,a gęstość zaludnienia jest mniejsza niż 10 000 osób na jednostkę powierzchni.

Wersja internetowa 9 modular

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

Informacje o indeksowaniu

Zanim uruchomisz zapytania, przeczytaj informacje o zapytaniach i Cloud Firestore modelu danych.

W 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 koszt 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ć kolekcję pracowników i znaleźć pracowników ze Stanów Zjednoczonych, których wynagrodzenie jest wyższe niż 100 000 USD, a staż pracy jest dłuższy niż 0 lat. Na podstawie znajomości zbioru danych wiesz, że ograniczenie dotyczące wynagrodzenia jest bardziej selektywne niż ograniczenie dotyczące stażu pracy. 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 porządkować 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 pola zakresu lub nierówności.

Cloud Firestore używa pól najbardziej z lewej strony indeksu złożonego, aby spełnić ograniczenia równości oraz ograniczenie zakresu lub nierówności (jeśli takie istnieje) w pierwszym polu zapytania orderBy() Te ograniczenia mogą zmniejszyć liczbę wpisów indeksu skanowanych przez Cloud Firestore. Cloud Firestore używa pozostałych pól indeksu, aby spełnić inne ograniczenia zakresu lub nierówności w zapytaniu. Te ograniczenia nie zmniejszają liczby wpisów indeksu skanowanych przez 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 ograniczenia zapytania. Wyższa selektywność dopasowuje mniejszy podzbiór dokumentów, a niższa selektywność – 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 indeksowania niż pola o niższej selektywności.

Aby zminimalizować liczbę dokumentów skanowanych i zwracanych przez Cloud Firestore w sieci, zawsze porządkuj pola w kolejności malejącej selektywności ograniczenia zapytania. Jeśli zbiór wyników nie jest w wymaganej kolejności i ma być mały, możesz zaimplementować logikę po stronie klienta, aby zmienić jego kolejność zgodnie z oczekiwaniami.

Załóżmy na przykład, że chcesz przeszukać kolekcję pracowników, aby znaleźć pracowników ze Stanów Zjednoczonych, których wynagrodzenie jest wyższe niż 100 000 USD, i uporządkować wyniki według stażu pracy pracownika. Jeśli spodziewasz się,że tylko niewielka liczba pracowników będzie miała wynagrodzenie wyższe niż 100 000 USD, najskuteczniejszym sposobem na napisanie zapytania jest:

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 porządkowania według experience spowoduje zwrócenie tego samego zbioru dokumentów i wyeliminuje konieczność zmiany kolejności wyników po stronie klienta, 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 pasują do klauzuli order by zapytania. Jeśli do klauzuli order by zostanie dodane experience, wtedy Cloud Firestore wybierze indeks (experience [...], salary [...]) do obliczania wyników zapytania. Ponieważ nie ma innych ograniczeń dotyczących experience, Cloud Firestore odczyta wszystkie wpisy indeksu kolekcji employees przed zastosowaniem filtra salary, aby znaleźć ostateczny zbiór wyników. Oznacza to, że wpisy indeksu, które nie spełniają filtra salary, są nadal odczytywane, co zwiększa opóźnienie i koszt zapytania.

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 Ceny.

Ograniczenia

Oprócz ograniczeń dotyczących zapytań przed użyciem zapytań z filtrami zakresu i nierówności w wielu polach weź pod uwagę te ograniczenia:

  • Zapytania z filtrami zakresu lub nierówności w polach dokumentu oraz tylko ograniczenia 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 kosztownym zapytaniom.

Co dalej?