For instance does retrieving a document which is in the sub collection of another document count as 1 read or 2?
A get of a document always costs one read. It doesn't matter if it's nested under any other documents. The other parent documents are not read.
Related
How to efficiently count the documents in a large Firestore collection.
Obviously, I do not want to get the entire collection and count it on the front end as the money will go through the roof. Is there really not a simple API such as db.collection('someCollection').count() or similar, but we need to hack around it?
(2022-10-20) Edit:
Starting from now, counting the documents in a collection or the documents that are returned by a query is actually possible without the need for keeping a counter. So you can count the documents using the new count() method which:
Returns a query that counts the documents in the result set of this query.
This new feature was announced at this year's Firebase summit. Keep in mind that this feature doesn't read the actual documents. So according to the official documentation:
For aggregation queries such as count(), you are charged one document read for each batch of up to 1000 index entries matched by the query. For aggregation queries that match 0 index entries, there is a minimum charge of one document read.
For example, count() operations that match between 0 and 1000 index entries are billed for one document read. For A count() operation that matches 1500 index entries, you are billed 2 document reads.
Is there really not a simple api such as db.collection('someCollection').count() or similar
No, there is not.
but we need to hack around it
Yes, we can use a workaround for counting the number of documents within a collection, which would be to keep a separate counter that should be updated every time a document is added to, or removed from the collection.
This counter can be added as a field inside a document in Firestore. However, if the documents in the collection are added or deleted very frequently, then this solution might be a little costly, a case in which I highly recommend you to use the Realtime Database. In this case, there is nothing you need to pay when you update the counter, but only when you read (download) it. And since it's just a number, then you'll have to pay almost nothing. I have even written an article a couple of years ago regarding solutions for counting documents in Firestore:
How to count the number of documents in a Firestore collection?
As the title suggests I would like to know how to get the total elements count of a paginated and filtered collection.
I have seen that many recommend, for the counting of the documents of the collection, to create a statistics document with the counter of the documents in the collection.
But if I need to implement a paged and filtered retrieval, how can I have the count of the total filtered items without having to retrieve them all?
Edit: October 20th, 2022
Starting from now, counting the documents in a collection or the documents that are returned by a query is actually possible without the need for keeping a counter. So you can count the documents using the new count() method which:
Returns a query that counts the documents in the result set of this query.
This new feature was announced at this year's Firebase summit. Keep in mind that this feature doesn't read the actual documents. So according to the [official documentation][2]:
For aggregation queries such as count(), you are charged one document read for each batch of up to 1000 index entries matched by the query. For aggregation queries that match 0 index entries, there is a minimum charge of one document read.
For example, count() operations that match between 0 and 1000 index entries are billed for one document read. For A count() operation that matches 1500 index entries, you are billed 2 document reads.
I have seen that many recommend, for the counting of the documents of the collection, creating a statistics document with the counter of the documents in the collection.
Yes, that is correct. It's very costly to count the number of documents within a collection, each time you need that total number. So it's best to have a field in a document that contains that number and increment it each time a new document is added and decrement it each time a document is deleted.
But if I need to implement a paged and filtered retrieval, how can I have the count of the total filtered items without having to retrieve them all?
There is no way you can know ahead of time, how many documents exist in a collection without reading them all or reading a document that contains that information, as explained above.
The pagination in NoSQL databases is a little different than in SQL databases. In all modern applications, we paginate the data using an infinite scroll. If you understand Java, then you can take a look at my answer in the following post:
How to paginate Firestore with Android?
Here is also the official documentation regarding Firestore pagination that can be achieved using query cursors:
https://firebase.google.com/docs/firestore/query-data/query-cursors
If you understand Kotlin, I also recommend you check the following resource:
How to implement pagination in Firestore using Jetpack Compose?
Is there a way to determine a read count for each document in Firestore? I would like to limit read counts to 100,000 per document.
(2022-10-20) Edit:
Starting from now, counting the documents in a collection or the documents that are returned by a query is actually possible without the need for keeping a counter. So you can count the documents using the new [count()][1] method which:
Returns a query that counts the documents in the result set of this query.
This new feature was announced at this year's Firebase summit. Keep in mind that this feature doesn't read the actual documents. So according to the [official documentation][2]:
For aggregation queries such as count(), you are charged one document read for each batch of up to 1000 index entries matched by the query. For aggregation queries that match 0 index entries, there is a minimum charge of one document read.
For example, count() operations that match between 0 and 1000 index entries are billed for one document read. For A count() operation that matches 1500 index entries, you are billed 2 document reads.
Is there a way to determine a read count for each document in Firestore?
As also #FrankvanPuffelen mentioned in his answer, there is no API for doing that. If you need such a mechanism you need to create it yourself. That means that each time a user reads a document, you should increment a counter. That's pretty simple to implement since Firestore provides a really straightforward solution for that. To keep a counter for each read, you can increment a field in a document using ServerValue.increment(1).
Here are the docs for Android:
https://firebase.google.com/docs/database/android/read-and-write#atomic_server-side_increments
Here are the docs for iOS:
https://firebase.google.com/docs/database/ios/read-and-write#atomic_server-side_increments
And here are for the web:
https://firebase.google.com/docs/database/web/read-and-write#atomic_server-side_increments
There is nothing built into Firestore to limit the number of reads for a specific document. There is a quota system (which a.o. is used to enforce the quota on the free plan), but that doesn't apply per document.
You could do this through cloud functions with onRequest or onCall:
Read a value from Realtime database
If the value is larger than 0, return the respective document.
Then decrement the value in Realtime database
Sources:
https://firebase.google.com/docs/database/web/read-and-write#atomic_server-side_increments
https://firebase.google.com/docs/functions/callable
When a collection is deleted from Cloud Firestore, its indexes are deleted along with it. I presume that when a collection goes from one or more documents to zero documents that its indexes are preserved. However, in the Cloud Firestore UI, when a collection goes from one document to zero the collection disappears from the root collections tree. Again, I presume this is an artifact of the Cloud Firestore UI, but it got me wondering whether something more happens when a collection becomes empty (as opposed to the collection being deleted outright).
Can you please help clarify what happens (if anything) when a collection goes from one or more documents to zero in Cloud Firestore? Do I need to be worried about losing any indexes when this occurs?
I'm neither Googler nor Firebaser, BUT...
Firestore indexes documents, not collections - the collection paths are an organizing principle more than physical entities. The "collections" are part of the path to documents, and it's the paths and the document fields that end up indexed.
Case in point: you can actually delete a collection while child documents remain, and they will still be indexed with the collection name/ID as part of their path - you'll see this in the console with the collection (and any interstitial document) names italicized.
When a collection goes from 1 to 0 documents, all that happens is that the document is gone, and nothing else. The UI sees no reason to display a collection when there is nothing to show.
Collections don't really "exist". They are just ways to organize documents for the purpose of making queries. What you see in the console is just there to help you visualize the contents of the database. Collections will apparently spring into "existence" when a document is first created, and just as quickly disappear when there are none. They do not work like directories in a filesystem.
An index is just a way of telling Firestore that you have special query needs for documents in a certain named collection or collection group. The index simply enables the query against the documents in the collection or collection group that you name. The index works without requiring any documents to index, and it will continue working no matter how many documents exist.
Some great answers by LeadDreamer and Doug already, but one more thing you seem to be curious about: deleting all documents from a collection does not affect the index definitions for that collection. So if you later add documents to the collection again, the same index definitions will still apply.
Firebase Firestore costs based on number of read operations. If I download a higher level document that has more then one sub-documents ( like Downloading a parent node that has more than one child node in Firebase Realtime Database.) then will it be considered as a single read or multiple read? I have not found any point about this in the documentation. Please explain?
Firestore queries are always shallow, and do not consider documents in subcollection. The only way to query for documents in subcollecitons is to target that subcollection with a separate query.
It does not work like Realitme Database, which gives you all child nodes with a parent node.