简体   繁体   English

如何计算 Firestore 集合下的文档数量?

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

I am trying to get CollectionReference count that exists on the Cloud Firestore, I have tried to get it with:我正在尝试获取 Cloud Firestore 上存在的CollectionReference计数,我尝试使用以下方法获取它:

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 ?有没有另一种方法来获得另一种修复IllegalStateException方法的计数?

Edit: July 10th, 2021编辑: 2021 年 7 月 10 日

Recently, Firebase added a new Extension called Distributed Counter :最近,Firebase 添加了一个名为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:因为我们在 Firebase 实时数据库中没有getDocumentCount()方法,一个getChildrenCount()方法来实际计算来自 Cloud Firestore 的Posts集合下的所有文档的数量,请使用以下代码:

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.一种方法是在每次从Posts集合中添加或删除文档时使用Cloud Functions更新counter 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 .但请注意,在这种情况下,文档的添加和删除只能以小于或等于每秒 1 次的速度发生,如Cloud Firestore 配额和限制中所述 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 .如果您需要超出此限制,则需要按照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.作为个人提示,不要在 Cloud Firestore 中存储这种计数器,因为每次增加或减少计数器都会花费您一次readwrite操作。 Host this counter in the Firebase Realtime database almost at no cost .Firebase Realtime数据库中几乎免费托管此计数器。

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.第二种方法是,而不是使用 Cloud Functions,在客户端使用事务,在添加或删除文档的同时更新计数器。 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.在这种情况下,您也可以免费使用 Firebase 实时数据库。

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.总之,对于小数据集使用第一个代码,第二个使用 Cloud Functions 因为是写入时尽力而为,第三个使用我在上面向您解释的最后一个选项。

inside onCompelete() check if (task.isSuccessful()) before using logs.在使用日志之前,在 onCompelete() 中检查if (task.isSuccessful()) 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并且您还可以像for (DocumentSnapshot document : task.getResult()){ yourCounter++;}迭代 documentSnapShot 并在每次迭代时增加counter以了解集合"Posts"有多少文档可用

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM