emulcahy
emulcahy

Reputation: 1065

Firestore query with multiple where clauses based on parameters

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.

Upvotes: 4

Views: 10788

Answers (2)

Pankaj
Pankaj

Reputation: 237

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();

Upvotes: 0

Doug Stevenson
Doug Stevenson

Reputation: 317362

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

Upvotes: 4

Related Questions