I have the following code to query properties (paginated) with filters:
const propertyCollectionRef = db.collection('properties')
let queryRef = propertyCollectionRef;
let query: any = db.collection('properties');
if (filters) {
for (const [key, value] of Object.entries(filters)) {
if (key !== 'page') {
switch (key) {
case "price":
query = query.where(key, '<=', parseInt(value));
break;
case "bathrooms":
query = query.where(key, '==', parseInt(value));
break;
case "beds":
query = query.where(key, '==', parseInt(value));
break;
case "min-area":
query = query.where("area", '>=', parseInt(value));
break;
case "max-area":
query = query.where("area", '<=', parseInt(value));
break;
case "typ":
query = query.where(key, '==', value);
break;
default:
query = query.where(key, '==', value);
break;
}
}
}
}
const offset = (page - 1) * pageSize
const querySnapshot = await query
.limit(pageSize)
.offset(offset).get();
firebase wants me to create an index for each query combination (
code: 9,
details: 'The query requires an index. You can create it here:...
) made when choosing different filters, for example, I need to create one for filtering price
and type
. but also one when filtering for price
, type
, and bathrooms
how is it possible to make this more "generic" – I can’t think of firebase to make it such complicated…
2
Answers
i will answer the question by my own and maybe for somebody who is also stepping across this situation:
in general its not possible to filter a collection as i did as in a in a compound query, range (<, <=, >, >=) and not equals (!=, not-in) comparisons must all filter on the same field - in my case i needed it for four range filter fields.
after checking the docs and some other repos i saw that in my situation it is the best to use only one range filter for the geoposition, to make this happen i use GeoFire which uses geohashes so only one field is required for the range filter. Please check out this video it is explained brilliant how to query for geopoints in firebase
i use then one more "equal" filter to decrease the loaded data with the rent type (for rent, for sale) ...
the rest of the range filters price, bathrooms, beds, ... are applied client side with a simpel
if/else
it's the best way i've found so far to handle my query
Cloud Firestore guarantees the query performance by requiring an index for every query. The indexes required for the most basic queries are automatically created for you. There is nothing that you should do. However, for more complex queries like yours, an index is required. One thing to notice is that you can create up to 200 indexes. If you need more than 200, then you can contact Firebase Support to request an increase to this limit.
Besides that, the indexes are created automatically. So that being said, queries like yours cannot work without creating indexes.
Yes, that’s correct. If you don’t want to do that yourself by clicking the URLs or by creating the indexes directly in the Firebase Console, then you should consider using the Firebase CLI. This allows you to deploy indexes with the Firebase CLI very easily.
For such queries, yes, here is a list of all query limitations in Firestore.