Firestore中如何统计一个集合下的文档数?
How to count the number of documents under a collection in Firestore?
我正在尝试获取 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
?
编辑: 2021 年 7 月 10 日
最近,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.
使用此扩展,您还可以突破一次写入的最大限制 operation/second。
这里还有一篇您可能感兴趣的文章:
因为我们在 Firebase 实时数据库中没有 getDocumentCount()
方法,getChildrenCount()
方法可以实际计算您的 Posts
集合下的所有文档的数量Firestore,请使用以下代码:
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());
}
}
});
上面的例子对于小数据集来说已经足够好了,但是如果数据集更大就不行了。但是,还有两种方法可以实现同样的目的。
一种方法是使用 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。这是一个单独的文档,但它几乎可以立即显示当前计数。
如果您需要超出此限制,您需要按照 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. Host this counter in the Firebase Realtime
database almost at no cost.
第二种方法是,不使用 Cloud Functions,而是在客户端使用事务,在添加或删除文档的同时更新计数器。这样,您的计数器也会准确,因为它是同时更新的。但在这种情况下,最重要的是您需要确保在添加或删除文档的任何地方都包含此逻辑。在这种情况下,您也可以免费使用 Firebase 实时数据库。
总之,第一个代码用于小型数据集,第二个代码使用 Cloud Functions,因为它是写入时尽力而为的,第三个使用我在上面向您解释过的最后一个选项。
在 onCompelete() 内部检查
if (task.isSuccessful())
在使用日志之前。并且您还可以像 for (DocumentSnapshot document : task.getResult()){ yourCounter++;}
一样遍历 documentSnapShot 并在每次迭代时递增 counter
以了解集合 "Posts"
下有多少文档可用
我确实通过这段代码解决了我的问题:
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;
}
}
});
我正在尝试获取 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
?
编辑: 2021 年 7 月 10 日
最近,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.
使用此扩展,您还可以突破一次写入的最大限制 operation/second。
这里还有一篇您可能感兴趣的文章:
因为我们在 Firebase 实时数据库中没有 getDocumentCount()
方法,getChildrenCount()
方法可以实际计算您的 Posts
集合下的所有文档的数量Firestore,请使用以下代码:
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());
}
}
});
上面的例子对于小数据集来说已经足够好了,但是如果数据集更大就不行了。但是,还有两种方法可以实现同样的目的。
一种方法是使用 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。这是一个单独的文档,但它几乎可以立即显示当前计数。
如果您需要超出此限制,您需要按照 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 awrite
operation. Host this counter in theFirebase Realtime
database almost at no cost.
第二种方法是,不使用 Cloud Functions,而是在客户端使用事务,在添加或删除文档的同时更新计数器。这样,您的计数器也会准确,因为它是同时更新的。但在这种情况下,最重要的是您需要确保在添加或删除文档的任何地方都包含此逻辑。在这种情况下,您也可以免费使用 Firebase 实时数据库。
总之,第一个代码用于小型数据集,第二个代码使用 Cloud Functions,因为它是写入时尽力而为的,第三个使用我在上面向您解释过的最后一个选项。
在 onCompelete() 内部检查
if (task.isSuccessful())
在使用日志之前。并且您还可以像 for (DocumentSnapshot document : task.getResult()){ yourCounter++;}
一样遍历 documentSnapShot 并在每次迭代时递增 counter
以了解集合 "Posts"
下有多少文档可用
我确实通过这段代码解决了我的问题:
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;
}
}
});