0

I want to count the number of branches of all restaurants. "Branch" is a sub collection of "Restaurants". When I try to do this query, there is an error:

rest.collection is not a function

Here's my code. How can I fix it?

async function getBranch(){ 
  const size = 0;
  const restRef = await firebase.firestore().collection('Restaurants').get();
  restRef.forEach((rest) => {
    const branchRef = rest.collection('Branch').get();
    size = size + branchRef.size();
  })
  return size;
}
Ashish
  • 6,791
  • 3
  • 26
  • 48

2 Answers2

1

you have to provide id of restaurants to get the subcollection. So better make reference for Restaurants and get all branches

async function getBranch(){ 
  const size = 0;
  const restRef = firebase.firestore().collection('Restaurants');
  const restRes = await restRef.get();
  restRef.forEach((rest) => {
    const branchRef = await restRef.doc(rest.id).collection('Branch').get();
    size = size + branchRef.size();
  })
  return size;
}
Ashish
  • 6,791
  • 3
  • 26
  • 48
  • Hi @Ashish, you should not use async/await in a forEach loop, see https://stackoverflow.com/search?q=forEach+async – Renaud Tarnec Oct 28 '20 at 12:49
  • In the loop the callback function is called but it does not wait for it to be completed before going to the next entry of the array. Have a look at https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404. To solve it, use the "technique" I indicated in my answer (`Promise.all()`) or other ones detailed in some of the answers I pointed to above. – Renaud Tarnec Oct 28 '20 at 14:14
0

You could do as follow, by using Promise.all() (untested).

async function getBranch(){ 
  let size = 0;
  const restQS = await firebase.firestore().collection('Restaurants').get();

  const promises = [];
  restQS.forEach((rest) => {
     promises.push(rest.collection('Branch').get());
  });

  const querySnapshotsArray = await Promise.all(promises);

  querySnapshotsArray.forEach(qs => {
     size += qs.size;   // <= Note that size is a property of the QuerySnapshot, not  a method
  })
  
  return size;
}

Another approach would be to query all your branch doc with a Collection group query, if the only collections named Branch are subcollection of Restaurants.

const branchQS = await firebase.firestore().collectionGroup('Branch').get();
return branchQS.size;

HOWEVER,

you should note that this implies that you read ALL the documents of ALL the (sub)collections each time you want to get the number of branch documents and, therefore, it has a cost.

So, if your collections have a lot of documents, a more affordable approach would be to maintain a set of distributed counters that hold the number of documents. Each time you add/remove a document, you increase/decrease the counters.

See here in the doc for more details, as well as this answer.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121