Query with range and inequality filters on multiple fields overview

Cloud Firestore supports using range and inequality filters on multiple fields in a single query. You can have range and inequality conditions on multiple fields and simplify yourapplication development by delegating implementation of post-filtering logic toCloud Firestore.

Range and inequality filters on multiple fields

The following query uses range filters on population and density to return allcities where population is higher than 1,000,000 people and population densityis less than 10,000 people per unit of area.

Web version 9 modular

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

Swift

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

Objective-C

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

Java Android

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

Kotlin+KTX Android

valquery=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

fromgoogle.cloudimportfirestoredb=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#

CollectionReferencecitiesRef=db.Collection("cities");Queryquery=citiesRef.WhereGreaterThan("Population",1000000).WhereLessThan("Density",10000);QuerySnapshotquerySnapshot=awaitquery.GetSnapshotAsync();foreach(DocumentSnapshotdocumentSnapshotinquerySnapshot){varname=documentSnapshot.GetValue<string>("Name");varpopulation=documentSnapshot.GetValue<int>("Population");vardensity=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++

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

Unity

CollectionReferencecitiesRef=db.Collection("cities");Queryquery=citiesRef.WhereGreaterThan("population",1000000).WhereLessThan("density",10000);

Dart

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

Indexing considerations

Before you run your queries, readaboutqueries and theCloud Firestoredata model.

InCloud Firestore, theORDER BY clause of a query determines which indexescan be used to serve the query. For example, anORDER BY a ASC, b ASC queryrequires a composite index on thea ASC, b ASC fields.

To optimize the performance and cost ofCloud Firestore queries,optimize the order of fields in the index. To do this, ensure that your index isordered from left to right such that the query distills to a dataset thatprevents scanning of unnecessary index entries.

Suppose you want to search through a collection of employees and find United Statesemployees whose salary is more than $100,000 and whose number of years of experience isgreater than 0. Based on your understanding of the dataset, you know that thesalary constraint is more selective than the experience constraint. The idealindex that would reduce the number of index scans would be the(salary [...], experience [...]). Thus, the query that would be fast andcost-efficient would ordersalary beforeexperience and look as follows:

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 practices for optimizing indexes

When optimizing indexes, note the following best practices.

Order index fields by equalities followed by most selective range or inequality field

Cloud Firestore uses the leftmost fields of a composite index to satisfy theequality constraints and the range or inequality constraint, if any, on the first fieldof theorderBy() query. These constraints can reduce the number of indexentries thatCloud Firestore scans.Cloud Firestore uses the remaining fieldsof the index to satisfy other range or inequality constraints of the query. Theseconstraints don't reduce the number of index entries thatCloud Firestore scansbut filter out unmatched documents so that the number of documents that arereturned to the clients are reduced.

For more information about creating efficient indexes, seeindex properties.

Order fields in decreasing order of query constraint selectivity

To ensure thatCloud Firestore selects the optimal index for your query,specify anorderBy() clause that orders fields in decreasing order of queryconstraint selectivity. Higher selectivity matches a smaller subset ofdocuments, while lower selectivity matches a larger subset of documents. Ensure thatyou select range or inequality fields with higher selectivity earlier in the indexordering than fields with lower selectivity.

To minimize the number of documents thatCloud Firestore scans and returns overthe network, you should always order fields in the decreasing order of queryconstraint selectivity. If the result set is not in the required order and theresult set is expected to be small, you can implement client-side logic toreorder it as per your ordering expectation.

For example, suppose you want to search through a collection of employees to findUnited States employees whose salary is more than $100,000 and order the results by the year ofexperience of the employee. If you expect only a small number of employees will have salariesgreater than $100,000, then the most efficient way to write the query is as follows:

Java

db.collection("employees").whereGreaterThan("salary",100000).orderBy("salary").get().addOnSuccessListener(newOnSuccessListener<QuerySnapshot>(){@OverridepublicvoidonSuccess(QuerySnapshotqueryDocumentSnapshots){// Order results by `experience`}});;

Node.js

constquerySnapshot=awaitdb.collection('employees').where("salary",">",100000).orderBy("salary").get();// Order results by `experience`

Python

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

While adding an ordering onexperience to the query will yield the same setof documents and obviate re-ordering the results on the clients, the query mayread many more extraneous index entries than the earlier query. This is becauseCloud Firestore always prefers an index whose index fields prefix match theorder by clause of the query. Ifexperience were added to the order by clause,thenCloud Firestore will select the(experience [...], salary [...]) indexfor computing query results. Since there are no other constraints onexperience,Cloud Firestore will readall index entries of theemployees collection before applying thesalary filter to find the finalresult set. This means that index entries which don't satisfy thesalaryfilter are still read, thus increasing the latency and cost of the query.

Pricing

Queries with range and inequality filters on multiple fields are billed based ondocuments read and index entries read.

For detailed information, see thePricing page.

Limitations

Apart from thequery limitations, note the following limitations beforeusing queries with range and inequality filters on multiple fields:

  • Queries with range or inequality filters on document fields and only equalityconstraints on the document key(__name__) aren't supported.
  • Cloud Firestore limits the number of range or inequality fields to 10. This is to prevent queries from becoming too expensiveto run.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-16 UTC.