4

I want to query a Firestore database with multiple where clauses based on the parameters that are passed in. The following block of code works:

getProducts2(accountId: string, manufacturer?: string, materialType?: string): Promise<Product[]> {
  return new Promise<Product[]>((resolve, reject) => {
    const productCollection2: AngularFirestoreCollection<FreightRule> = this.afs.collection('products');

    const query = productCollection2.ref
      .where('materialType', '==', materialType)
      .where('manufacturer', '==', manufacturer);

    query.get().then(querySnapshot => {
      if (querySnapshot.size > 0) {
        const data = querySnapshot.docs.map(documentSnapshot => {
          return documentSnapshot.data();
        }) as Product[];
        resolve(data);
      } //todo else...
    });
  });
}

But what I really want to do is conditionally include the where clauses based on the optional parameters. The following is what I want, but it doesn't work:

getProducts2(accountId: string, manufacturer?: string, materialType?: string): Promise<Product[]> {
  return new Promise<Product[]>((resolve, reject) => {
    const productCollection2: AngularFirestoreCollection<FreightRule> = this.afs.collection('products');

    const query = productCollection2.ref;
    if (manufacturer) {
      query.where('manufacturer', '==', manufacturer);
    }
    if (materialType) {
      query.where('materialType', '==', materialType);
    }

    query.get().then(querySnapshot => {
      if (querySnapshot.size > 0) {
        const data = querySnapshot.docs.map(documentSnapshot => {
          return documentSnapshot.data();
        }) as Product[];
        resolve(data);
      } //todo else...
    });
  });
}

While valid, this code just returns all of the products with no filtering.

Is there a way to structure this so I can filter based on the optional parameters?

edit: I realize I can do something like:

let query;
if (manufacturer && materialType) {
  query = productCollection2.ref.where(....).where(....)
} else if (manufacturer) {
  query = productCollection2.ref.where(....)
} else if (materialType) {
  query = productCollection2.ref.where(....)
}

I was just hoping for something a little more elegant.

2 Answers 2

4

Build upon the prior query, don't repeat the prior query:

let query = collection  // initial query, no filters
if (condition1) {
    // add a filter for condition1
    query = query.where(...)
}
if (condition2) {
    // add a filter for condition2
    query = query.where(...)
}
// etc
Sign up to request clarification or add additional context in comments.

6 Comments

Got it, thank you. I needed to assign query.where to query.
This really helped! I was looking for something similar to \u2731 which would be * and in sql matches "any". But this solution works as well.
this answer is perfect, it helps me on android too.... i was trying to filter data without any good result until i saw this answer.. thanks stackoverflow for existing
Doug, I tried query = query.where(...) and get IntelliSense error "Property 'where' does not exist on type 'AngularFirestoreCollection<abc>'". Any idea why it's not working?
@JimBistis If you have a question, you should post it separately with a full explanation of what isn't working the way you expect with your code.
|
0

If using different query structure, You can try below ways:

db.collection("subscriptions").where("email", '==', req.body.email,"&&","subscription_type","==","free").get();

OR

db.collection("subscriptions").where("email", '==', req.body.email).where("subscription_type", '==', 'free111').get();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.