0
votes

I am trying to build a dynamic query for firestore using this approach: Cloud Firestore - Dynamic Querying

Here is how I build my query:

buildQueryRef(ref: firebase.firestore.CollectionReference, queryMap: ProductQueryMap, lastDoc?: Item) {

    var query : Query = ref; 
    
    if (queryMap.minPrice)
      query = query.where("price", ">=", queryMap.minPrice) || ref.where("price", ">=", queryMap.minPrice);

    if (queryMap.maxPrice)
      query = query.where("price", "<=", queryMap.maxPrice) || ref.where("price", "<=", queryMap.maxPrice);

    if (queryMap.type)
      query = query.where("type", "==", queryMap.type) || ref.where("type", "==", queryMap.type);

    if (queryMap.orType)
      query = query.where("type", "in", queryMap.type) || ref.where("type", "in", queryMap.type);

    if (queryMap.status)
      query = query.where("status", "in", queryMap.status) || ref.where("status", "in", queryMap.status);

    if (queryMap.keywords || queryMap.orKeywords)
      query = query.where("keywords", "array-contains-any", queryMap.keywords) || ref.where("keywords", "array-contains-any", queryMap.keywords);

    if (queryMap.userId) {
      query = query.where("userId", "==", queryMap.userId) || ref.where("userId", "==", queryMap.userId);
      // query.orderBy("userId", "desc");
      // orderArr.push("userId");
    }
    if (queryMap.minPrice || queryMap.maxPrice)
      query = query.orderBy("price", "asc") || ref.orderBy("price", "asc");

    query = query.orderBy("created", "desc") || ref.orderBy("created", "desc");

    if (lastDoc)

      query = query.startAfter(lastDoc.created) || ref.startAfter(lastDoc.created);

    query = query.limit(12) || ref.limit(12);
    return query;
  }

So, for example, if I make a query that has no parameters, it will only set the orderBy("created", "desc") and limit(12) and will work just fine, but as soon as it receives any other parameters like userId or type it returns no documents.

At first there was an error message with a link to create a composite index in firestore, but then I created the indexes as suggested and then it didn't return any documents.

I want to know if it is possible to make queries with this approach, because it would not be practical to write a query for every possible combination of parameters.

Thanks in advance.

1
This is not needed: query = query.where("price", ">=", queryMap.minPrice) || ref.where("price", ">=", queryMap.minPrice);. Instead you can just do query = query.where("price", ">=", queryMap.minPrice);.Frank van Puffelen

1 Answers

0
votes

Firestore requires that indexes must be present before making a query successfully. How you create them is up to you, but it's not an optional step. If you have a lot of combinations of ordering and filters to apply, you will either have to create them all manually as you have been, or find some way to automate that.

You might find it helpful to generate a JSON description of indexes to deploy with the Firebase CLI, or invoke the REST API directly. Either way, it is not trivial work.