Panoramica delle query con filtri per intervallo e disuguaglianza su più campi

Firestore supporta l'utilizzo di filtri per intervallo e disuguaglianza su più campi in una singola query. Ora puoi disporre di condizioni di intervallo e disuguaglianza su più campi e semplificare lo sviluppo delle applicazioni delegando l'implementazione della logica di post-filtro a Firestore.

Filtri di intervallo e disuguaglianza in più campi

La seguente query restituisce tutti gli utenti con età superiore a 35 anni e altezza compresa tra 60 e 70 anni utilizzando i filtri di intervallo per età e altezza.

Versione web modulare 9

  const q = query(
      collection(db, "users"),
      where('age', '>', 35),
      where('height', '>', 60),
      where('height', '<', 70)
    );

Swift

 let query = db.collection("users")
   .whereField("age", isGreaterThan: 35)
   .whereField("height", isGreaterThan: 60)
   .whereField("height", isLessThan: 70)

Objective-C

 FIRQuery *query = 
  [[[[self.db collectionWithPath:@"users"]
 queryWhereField:@"age" isGreaterThan:@35]
    queryWhereField:@"height" isGreaterThan:@60] 
        queryWhereField:@"height" isLessThan:@70];

Android Java

 Query query = db.collection("users")
  .whereGreaterThan("age", 35)
  .whereGreaterThan("height", 60)
  .whereLessThan("height", 70);

Kotlin+KTX per Android

 val query = db.collection("users")
  .whereGreaterThan("age", 35)
  .whereGreaterThan("height", 60)
  .whereLessThan("height", 70)

Java

  db.collection("users")
    .whereGreaterThan("age", 35)
    .whereGreaterThan("height", 60)
    .whereLessThan("height", 70);

Node.js

db.collection("users")
  .where('age', '>', 35),
  .where('height', '>', 60),
  .where('height', '<', 70)

Considerazioni sull'indicizzazione

Prima di iniziare a eseguire le query, assicurati di aver letto le query e il modello dei dati di Firestore.

In Firestore, la clausola ORDER BY di una query determina quali indici possono essere utilizzati per eseguire la query. Ad esempio, una query ORDER BY a ASC, b ASC richiede un indice composto nei campi a ASC, b ASC.

Per ottimizzare le prestazioni e il costo delle query Firestore, dovresti ottimizzare l'ordine dei campi nell'indice. Per farlo, devi assicurarti che l'indice sia ordinato da sinistra a destra, in modo che la query si confonda in un set di dati che impedisce l'analisi delle voci di indice estranee.

Supponiamo che tu voglia cercare in un gruppo di dipendenti e trovare dipendenti con stipendio superiore a 100.000 e con anni di esperienza superiore a 0. In base alla tua comprensione del set di dati, sai che il vincolo retributivo è più selettivo di quello sull'esperienza. L'indice ideale che ridurrebbe il numero di scansioni dell'indice sarebbe (salary [...], experience [...]). Di conseguenza, per una query veloce ed economicamente vantaggiosa si ordina salary prima di experience e si presenta come segue:

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

Best practice per l'ottimizzazione degli indici

Quando ottimizzi gli indici, tieni presente le seguenti best practice.

Ordina i campi dell'indice in base alle uguaglianze seguite dal campo intervallo o disuguaglianza più selettivo

Firestore utilizza i campi più a sinistra di un indice composto per soddisfare i vincoli di uguaglianza e l'eventuale vincolo di intervallo o disuguaglianza nel primo campo della query orderBy(). Questi vincoli possono ridurre il numero di voci di indice analizzate da Firestore. Firestore utilizza i campi rimanenti dell'indice per soddisfare altri vincoli di intervallo o disuguaglianza della query. Questi vincoli non riducono il numero di voci di indice analizzate da Firestore, ma filtrano i documenti senza corrispondenza in modo da ridurre il numero di documenti restituiti ai client.

Per saperne di più sulla creazione di indici efficienti, consulta la definizione di un indice perfetto.

Ordina i campi in ordine decrescente di selettività del vincolo di query

Per assicurarti che Firestore selezioni l'indice ottimale per la query, specifica una clausola orderBy() che ordini i campi in ordine decrescente di selettività del vincolo di query. Una selettività maggiore corrisponde a un sottoinsieme più di documenti più piccolo, mentre una selettività inferiore corrisponde a un sottoinsieme più ampio di documenti. Assicurati di selezionare i campi di intervallo o disuguaglianza con una selettività più alta prima nell'ordinamento dell'indice rispetto ai campi con selettività più bassa.

Per ridurre al minimo il numero di documenti che Firestore analizza e restituisce sulla rete, devi sempre ordinare i campi in ordine decrescente di selettività del vincolo di query. Se il set di risultati non è nell'ordine richiesto e si prevede che sia di dimensioni ridotte, puoi implementare la logica lato client per riordinarlo in base alle tue aspettative di ordinamento.

Ad esempio, supponiamo che tu voglia cercare in un gruppo di dipendenti per trovare dipendenti con uno stipendio superiore a 100.000 e ordinare i risultati in base all'anno di esperienza del dipendente. Se prevedi che solo un numero limitato di dipendenti avrà uno stipendio superiore a 100.000, il modo più efficiente per scrivere la query è il seguente:

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`

Mentre l'aggiunta di un ordinamento su experience alla query restituirà lo stesso insieme di documenti e impedirà il riordinamento dei risultati sui client, la query potrebbe leggere molte più voci di indice estranee rispetto alla query precedente. Questo perché Firestore preferisce sempre un indice il cui prefisso dei campi indice corrisponda alla clausola di ordine per ordine della query. Se experience è stato aggiunto alla clausola Ordina per, Firestore selezionerà l'indice (experience [...], salary [...]) per calcolare i risultati delle query. Poiché non esistono altri vincoli su experience, Firestore leggerà tutte le voci di indice della raccolta employees prima di applicare il filtro salary per trovare il set di risultati finale. Ciò significa che le voci di indice che non soddisfano il filtro salary vengono comunque lette, aumentando così la latenza e il costo della query.

Prezzi

Le query con filtri per intervallo e disuguaglianza su più campi vengono fatturate in base ai documenti letti e alle voci di indice lette.

Per informazioni dettagliate, consulta la pagina Prezzi.

Limitazioni

A parte le limitazioni per le query, tieni presente le seguenti limitazioni prima di utilizzare query con filtri di intervalli e disuguaglianze su più campi:

  • Le query con filtri di intervallo o disuguaglianza nei campi dei documenti e solo vincoli di uguaglianza nella chiave (__name__) del documento non sono supportate.
  • Firestore limita il numero di campi di intervallo o disuguaglianza a 10. per evitare che le query diventino troppo costose da eseguire.

Passaggi successivi