Как подсчитать количество документов в коллекции в Firestore?
Я пытаюсь получить количество CollectionReference, которое существует в облачном Firestore, я пытался получить его с помощью:
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
?
Переведено автоматически
Ответ 1
Редактировать: 20 октября 2022 г.
Начиная с этого момента, подсчет документов в коллекции или документов, возвращаемых запросом, фактически возможен без необходимости ведения счетчика. Таким образом, вы можете подсчитать документы, используя новый метод count(), который:
Возвращает запрос, который подсчитывает документы в результирующем наборе этого запроса.
Эта новая функция была анонсирована на саммите Firebase в этом году. Имейте в виду, что эта функция не считывает фактические документы. Итак, согласно официальной документации:
Для запросов агрегирования, таких как count(), с вас взимается плата за один прочитанный документ за каждый пакет, содержащий до 1000 записей индекса, соответствующих запросу. Для запросов агрегации, которые соответствуют 0 индексным записям, взимается минимальная плата за одно прочтение документа.
Например, за операции count(), которые соответствуют от 0 до 1000 записей индекса, выставляется счет за одно чтение документа. За операцию count(), которая соответствует 1500 записям индекса, выставляется счет за 2 чтения документа.
Редактировать: 10 июля 2021 г.
Недавно Firebase добавила новое расширение под названием Распределенный счетчик:
Используйте это расширение, чтобы добавить в свое приложение масштабируемый сервис счетчиков. Это идеальное решение для приложений, которые подсчитывают вирусные действия или любые действия с высокой скоростью, такие как просмотры, лайки или публикации.
Используя это расширение, вы также можете превысить максимальное ограничение в одну операцию записи в секунду.
Здесь также есть статья, которая может вас заинтересовать:
Поскольку нет getDocumentCount()
метода, который есть в базе данных Firebase Realtime database, 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());
}
}
});
Приведенные выше примеры достаточно хорошо работают для небольших наборов данных, но они не работают, если набор данных больше. Но есть еще два способа, которыми вы можете добиться того же.
Одним из способов было бы использовать облачные функции для обновления counter
каждый раз, когда вы добавляете или удаляете документ из своей Posts
коллекции. Этот метод хорошо работает также для больших наборов данных. Но обратите внимание, что в этом случае добавления и удаления документов могут происходить только со скоростью, меньшей или равной 1 в секунду, как описано в Cloud Firestore Quotes and Limits. Это один документ для чтения, но он показывает текущее количество практически мгновенно.
Если вам необходимо превысить это ограничение, вам необходимо реализовать distributed counters
как описано в официальной документации распределенных счетчиков.
В качестве личного совета, не храните этот счетчик в облачном Firestore, потому что каждый раз, когда вы увеличиваете или уменьшаете счетчик, это будет стоить вам
read
илиwrite
операции. Разместите этот счетчик вFirebase Realtime
базе данных практически бесплатно.
Вторым способом было бы, вместо использования облачных функций, использовать транзакции на стороне клиента, обновлять счетчик одновременно с добавлением или удалением документа. Таким образом, ваш счетчик также будет точным, потому что он обновляется одновременно. Но самое главное, в данном случае, это то, что вам нужно обязательно включать эту логику везде, где вы добавляете или удаляете документ. В этом случае вы также можете бесплатно использовать базу данных Firebase в реальном времени.
В заключение, используйте первый код для небольших наборов данных, во втором используйте облачные функции, потому что это требует наилучших затрат времени на запись, а в третьем используйте последний вариант, который я объяснил вам выше.
Ответ 2
Я решил свою проблему с помощью этого кода:
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;
}
}
});
Ответ 3
внутри onCompelete() проверьте if (task.isSuccessful())
перед использованием журналов. а также вы можете выполнить итерацию по documentSnapShot, например, for (DocumentSnapshot document : task.getResult()){ yourCounter++;}
и увеличивать counter
на каждой итерации, чтобы узнать, сколько документов в коллекции "Posts"
доступно