如何计算Firestore中集合下的文档数量?
我正在尝试获取Cloud Firestore上存在的CollectionReference计数,我试图通过以下方式获取它:
FirebaseFirestore db = FirebaseFirestore.getInstance(); final CollectionReference postsCollection = db.collection("Posts"); final TaskCompletionSource source = new TaskCompletionSource(); new Thread(new Runnable() { @Override public void run() { int fromWhereToStart = postsCollection.get().getResult().size(); source.setResult(fromWhereToStart); } }).start(); Task task = source.getTask(); task.addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { Log.e("Z_fromWhereToStart", "= " + task.getResult()); } });
但不幸的是,我得到了:
java.lang.IllegalStateException: Task is not yet complete
是否有另一种方法来计算修复IllegalStateException
的另一种方法?
我们在Firebase Realtime数据库中没有getDocumentCount()
方法,这是一个getChildrenCount()
方法,要实际计算您的Cloud Firestore中Posts
集合下所有文档的数量,请使用以下代码:
db.collection("Posts").get().addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task 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() { @Override public void onComplete(@NonNull Task 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配额和限制中所述 。 这是一个要阅读的单个文档,但它几乎可以立即显示当前计数。
如果您需要超出此限制,则需要按照distributed counters
的官方文档中的说明实现分布式计数器 。
作为个人提示,请勿在Cloud Firestore中存储此类计数器,因为每次增加或减少计数器都会花费您的
read
或write
操作。 在Firebase Realtime
数据库中免费托管此计数器。
第二种方法是,而不是使用云function,在客户端使用事务,在添加或删除文档的同时更新计数器。 这样,您的计数器也将是准确的,因为它会同时更新。 但在这种情况下最重要的是,您需要确保在添加或删除文档的任何位置包含此逻辑。 在这种情况下,您可以免费使用Firebase实时数据库。
作为结论,使用第一个代码用于小型数据集,第二个使用云函数,因为写入时间尽力而为,第三个使用我上面解释过的最后一个选项。
在onCompelete()内部,在使用日志之前检查if (task.isSuccessful())
。 并且你可以像for (DocumentSnapshot document : task.getResult()){ yourCounter++;}
一样遍历documentSnapShot并在每次迭代时递增counter
,以了解收集"Posts"
有多少文档可用