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

Posted

技术标签:

【中文标题】如何计算 Firestore 中集合下的文档数?【英文标题】:How to count the number of documents under a collection in Firestore? 【发布时间】:2018-07-10 02:54:15 【问题描述】:

我正在尝试获取 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());
        
    );

但不幸的是,我得到了:

java.lang.IllegalStateException: Task is not yet complete

是否有另一种方法来计算修复IllegalStateException 的另一种方法?

【问题讨论】:

在使用日志之前在 onCompelete() 中检查if (task.isSuccessful())。您还可以像for (DocumentSnapshot document : task.getResult()) yourCounter++; 一样遍历documentSnapShot,并在每次迭代时递增计数器,以了解“帖子”集合下有多少文档可用。 谢谢,我已经尝试过 'if (task.isSuccessful())' 以确保它不起作用,问题出在 Integer fromWhereToStart 的行中,我也没有使用 count++因为我只是添加数据不需要获取整个文档,但是如果我找不到解决方案,我可能会使用这个想法,再次感谢您 所以您要计算Posts 集合中的所有文档?这是你想要的吗? @AlexMamo 是的,有没有办法在不获取整个数据的情况下获取计数 @MohammedFarhan 你也可以添加你的评论作为答案 【参考方案1】:

编辑: 2021 年 7 月 10 日

最近,Firebase 添加了一个名为Distributed Counter 的新扩展:

使用此扩展程序为您的应用添加高度可扩展的计数器服务。这对于计算病毒式操作或任何非常高速的操作(例如查看、喜欢或分享)的应用程序来说是理想的。

使用此扩展,您还可以超过每秒一次写入操作的最大限制。

这里还有一篇您可能感兴趣的文章:

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

因为我们在 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());
        
    
);

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

上面的例子对于小数据集来说已经足够好,但是如果数据集更大就不行了。但是,还有另外两种方法可以实现相同的目标。

一种方法是在每次从Posts 集合中添加或删除文档时使用Cloud Functions 更新counter。这种技术也适用于大数据集。但请注意,在这种情况下,文档的添加和删除只能以每秒小于或等于 1 的速率发生,如Cloud Firestore Quotas and Limits 中所述。这是一个要阅读的文档,但它几乎可以立即向您显示当前计数。

如果您需要超出此限制,您需要按照official documentation of distributed counters 中的说明实施distributed counters

作为个人提示,不要将这种计数器存储在 Cloud Firestore 中,因为每次增加或减少计数器都会花费您一次 readwrite 操作。在Firebase Realtime 数据库中托管此计数器几乎免费

第二种方法是,而不是使用 Cloud Functions,而是在客户端使用事务,在添加或删除文档的同时更新计数器。这样,您的计数器也会准确,因为它是同时更新的。但在这种情况下,最重要的是,您需要确保在添加或删除文档的任何地方都包含此逻辑。在这种情况下,您也可以免费使用 Firebase 实时数据库。

总之,将第一个代码用于小型数据集,第二个代码使用 Cloud Functions,因为它是写入时的尽力而为,第三个代码使用我在上面向您解释过的最后一个选项。

【讨论】:

谢谢,这行得通,但是没有获取全部数据就没有办法获取它们吗? 不幸的是,我们在 Firebase 实时数据库 getChildrenCout() 中没有 getDocumentCount() 方法。 非常感谢您的帮助,我认为他们必须为我创建一个方法然后 xD 请看我更新的答案。希望您对 Cloud Firestore 中的文档计数有更好的了解。 这与谁先回答无关,而是您需要检查是否已接受您认为对您更有用的答案。这也将有助于将来阅读问题/答案的访问者。【参考方案2】:

在 onCompelete() 内部检查 if (task.isSuccessful())使用日志之前。您还可以像for (DocumentSnapshot document : task.getResult()) yourCounter++; 一样遍历documentSnapShot,并在每次迭代时递增counter,以了解集合"Posts" 下有多少文档可用

【讨论】:

【参考方案3】:

我确实通过这段代码解决了我的问题:

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

【讨论】:

纯代码答案并不是特别有用。请添加一些关于此代码如何解决问题的说明。

以上是关于如何计算 Firestore 中集合下的文档数?的主要内容,如果未能解决你的问题,请参考以下文章

在 React 本机移动应用程序中集成 firestore 时获得“firestore/permission-denied”

FireStore 文档如何在子集合中读取计算

Firebase Firestore 中一个集合下的文档数量限制

如何使用 Flutter 在 Firestore 中删除具有特定值的多个文档

如何在flutter中将具有文档ID的自定义对象设置为firestore中的集合?

在 Cloud Firestore 中更新集合名称