How to count the number of documents under a collection in Firestore?

12,194

Solution 1

Edit: July 10th, 2021

Recently, Firebase added a new Extension called Distributed Counter:

Use this extension to add a highly scalable counter service to your app. This is ideal for applications that count viral actions or any very high-velocity action such as views, likes, or shares.

Using this Extension, you can also get over the max limit of one write operation/second.

Here is also an article that you might be interested in:


Becasue there is no getDocumentCount() method as we have in Firebase Realtime database, a getChildrenCount() method, to actually count the number of all documents beneath your Posts collection from your Cloud Firestore, please use the following code:

db.collection("Posts").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        if (task.isSuccessful()) {
            int count = 0;
            for (DocumentSnapshot document : task.getResult()) {
                count++;
            }
            Log.d("TAG", count + "");
        } else {
            Log.d(TAG, "Error getting documents: ", task.getException());
        }
    }
});

or

db.collection("Posts").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        if (task.isSuccessful()) {
            Log.d("TAG", task.getResult().size() + "");
        } else {
            Log.d(TAG, "Error getting documents: ", task.getException());
        }
    }
});

The above examples work well enough for small datasets but it doesn't work if the dataset is larger. But, there are also two more ways in which you can achieve the same thing.

One way would be to use Cloud Functions to update a counter every time you add or delete a document from your Posts collection. This technique works well also for big datasets. But note, in this case, the additions and deletions of documents can only occur at the rate less than or equal to 1 per second, as described in Cloud Firestore Quotas and Limits. That is a single document to read but it shows you the current count almost instantly.

If there is a need for you to exceed this limitation, you need to implement distributed counters as explained in the official documentation of distributed counters.

As a personal hint, don't store this kind of counter in Cloud Firestore, because every time you increase or decrease the counter will cost you a read or a write operation. Host this counter in the Firebase Realtime database almost at no cost.

The second way would be, rather than using Cloud Functions, to use transactions at your client-side, to update the counter at the same time as you add or delete a document. In this way, your counter will also be accurate, because it is updated at the same time. But the most important thing, in this case, is that you'll need to make sure to include this logic anywhere you add or delete a document. You can use in this case Firebase Realtime database as well, at no cost.

In conclusion, use the first code for small datasets, the second use Cloud Functions because is write-time best-effort, and the third use the last option I have explained to you above.

Solution 2

inside onCompelete() check if (task.isSuccessful())before using logs. and also you can iterate over the documentSnapShot like for (DocumentSnapshot document : task.getResult()){ yourCounter++;} and increment counter on each iteration to know how many documents under collection "Posts" are available

Solution 3

I did solve my problem by this code:

db.collection("Posts").get().addOnCompleteListener(new 
 OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        if (task.isSuccessful()) {
               count = task.getResult().size();              
        } else {
               Toast.makeTesxt(getContext(),"Error : " + 
                                         e.toString(),Toast.LENGHT_LONG).show;
        }
     }
});
Share:
12,194
Dasser Basyouni
Author by

Dasser Basyouni

I'm a self-taught Android Developer passionate about learning and developing Android applications. I recently graduated from the Advanced Android Developer Nanodegree program of Udacity. I am looking forward to applying my acquired skills in the field and help others.

Updated on June 11, 2022

Comments

  • Dasser Basyouni
    Dasser Basyouni about 2 years

    I am trying to get CollectionReference count that exists on the Cloud Firestore, I have tried to get it with:

    FirebaseFirestore db = FirebaseFirestore.getInstance();
        final CollectionReference postsCollection = db.collection("Posts");
    
        final TaskCompletionSource<Integer> source = new TaskCompletionSource<>();
        new Thread(new Runnable() {
            @Override
            public void run() {
                int fromWhereToStart = postsCollection.get().getResult().size();
                source.setResult(fromWhereToStart);
            }
        }).start();
    
        Task<Integer> task = source.getTask();
        task.addOnCompleteListener(new OnCompleteListener<Integer>() {
            @Override
            public void onComplete(@NonNull Task<Integer> task) {
                Log.e("Z_fromWhereToStart", "= " + task.getResult());
            }
        });
    

    But unfortunately, I'm getting:

    java.lang.IllegalStateException: Task is not yet complete
    

    Is there is another way to get the count of another way to fix the IllegalStateException?

  • Dasser Basyouni
    Dasser Basyouni over 6 years
    Thank you, that is working but is there isn't a way to get them without getting the whole data?
  • Alex Mamo
    Alex Mamo over 6 years
    Unfortunatelly, there is not getDocumentCount() method as we have in Firebase Realtime database, getChildrenCout().
  • Dasser Basyouni
    Dasser Basyouni over 6 years
    thank so much for your help, I think they have to create a method for me then xD
  • Alex Mamo
    Alex Mamo over 6 years
    I'll update my answer with few more specifications in a few minutes.
  • Alex Mamo
    Alex Mamo over 6 years
    Please see my updated answer. Hope you'll have a better understanding regarding counting documents in Cloud Firestore.
  • Dasser Basyouni
    Dasser Basyouni over 6 years
    sorry for the late reply, thank you so much for your perfect explained answer appreciated, I don't know which answer deserve the accepted sign, is it the first one who answers?
  • Alex Mamo
    Alex Mamo over 6 years
    It's not about who has answered first, it's your call to check as accepted the answer that you think is more useful for you. This will also help future visitors that will read the question/answer.
  • Dasser Basyouni
    Dasser Basyouni over 6 years
    thank you for explaining to me this point, have a nice day you and Mohammed
  • Mohammed Farhan
    Mohammed Farhan over 6 years
    @AlexMamo thanks for introducing distributed counters concepts. Cheers!
  • Mohammed Farhan
    Mohammed Farhan over 6 years
    @AlexMamo you deserve more than one +1
  • tccpg288
    tccpg288 over 6 years
    This solution is for .get() - what about if you use .addSnapshotListener() for realtime updates?
  • Alex Mamo
    Alex Mamo over 6 years
    @tccpg288 .addSnapshotListener() is used to listen to document changes.
  • Al Foиce    ѫ
    Al Foиce ѫ about 3 years
    Code-only answers are not particularly helpful. Please add some descriptions of how this code solves the problem.