irebase  ](/docs/gemini-in-firebase)

  * [ Emulator Suite  ](/docs/emulator-suite)
  * [ Authentication  ](/docs/auth)
  * [ Realtime Database  ](/docs/database)
  * [ Firestore  ](/docs/firestore)
  * [ Storage  ](/docs/storage)
  * [ ML  ](/docs/ml)
  * [ Hosting  ](/docs/hosting)
  * [ Cloud Functions  ](/docs/functions)
  * [ Security Rules  ](/docs/rules)
  * [ App Check  ](/docs/app-check)
  * [ Extensions  ](/docs/extensions)

  * [ Crashlytics  ](/docs/crashlytics)
  * [ Performance Monitoring  ](/docs/perf-mon)
  * [ Test Lab  ](/docs/test-lab)
  * [ App Distribution  ](/docs/app-distribution)

  * [ Analytics  ](/docs/analytics)
  * [ Remote Config  ](/docs/remote-config)
  * [ A/B Testing  ](/docs/ab-testing)
  * [ Cloud Messaging  ](/docs/cloud-messaging)
  * [ In-App Messaging  ](/docs/in-app-messaging)
  * [ Dynamic Links  ](/docs/dynamic-links)
  * [ Google AdMob  ](/docs/admob)
  * [ Google Ads  ](/docs/ads)
  * [ App Indexing  ](/docs/app-indexing)

Firebase is back at Google I/O on May 14! [ Register now.
](https://io.google/2024/?utm_source=firebase&utm_medium=embedded_marketing&utm_campaign=&utm_content=)

  * [ Firebase ](https://firebase.google.com/)
  * [ Documentation ](https://firebase.google.com/docs)
  * [ Firestore ](https://firebase.google.com/docs/firestore)
  * [ Build ](https://firebase.google.com/docs/build)

Send feedback

#  Optimize queries with range and inequality filters on multiple fields

Stay organized with collections  Save and categorize content based on your
preferences.

**Note:** This feature is a public preview. This means that the functionality
might change in backward-incompatible ways. A preview release is not subject
to any SLA or deprecation policy and may receive limited or no support.

This page provides examples of indexing strategy that should be used for
queries with range & inequality filters on multiple fields to create an
efficient query experience.

Read about [ the related concepts ](/docs/firestore/query-data/multiple-range-
fields) before optimizing your queries.

##  Optimize queries with Query Explain

To determine if the query and indexes used are optimal, you can use [ Query
Explain ](/docs/firestore/query-explain) to get the query plan summary and
execution statistics of the query:

###  Java

    
    
    Query q = db.collection("employees").whereGreaterThan("salary",
    100000).whereGreaterThan("experience", 0);
    
    ExplainResults<QuerySnapshot> explainResults = q.explain(ExplainOptions.builder().analyze(true).build()).get();
    ExplainMetrics metrics = explainResults.getMetrics();
    
    PlanSummary planSummary = metrics.getPlanSummary();
    ExecutionStats executionStats = metrics.getExecutionStats();
    
    System.out.println(planSummary.getIndexesUsed());
    System.out.println(stats.getResultsReturned());
    System.out.println(stats.getExecutionDuration());
    System.out.println(stats.getReadOperations());
    System.out.println(stats.getDebugStats());
    

###  Node.js

    
    
    let q = db.collection("employees")
          .where("salary", ">", 100000)
          .where("experience", ">",0);
    
    let options = { analyze : 'true' };
    let explainResults = await q.explain(options);
    
    let planSummary = explainResults.metrics.planSummary;
    let stats = explainResults.metrics.executionStats;
    
    console.log(planSummary);
    console.log(stats);
    

The following example shows how the use of correct index ordering reduces the
number of index entries that Cloud Firestore scans.

###  Simple queries

With the [ earlier example ](/docs/firestore/query-data/multiple-range-
fields#indexing_considerations) of a collection of employees, the simple query
that runs with the ` (experience ASC, salary ASC) ` index is as follows:

###  Java

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

The