I have a large collection of large documents stored in Firestore. As fetching the entire collection would be costly, I would like to fetch a list of document ids for my user and only fetch the document data after my user makes his selection.
This is how I’m fetching the documents ids
const querySnapshot = await db
.collection("myCollection")
.get()
const ids = querySnapshot.docs.map((document) => document.id);
Unfortunately, I believe that the above code fetches both the document id as well as the document data. Is there any way to fetch only the document id without fetching the document data?
If the above is not possible due to Firestore’s limitations, what is the best practice for maintaining a second collection to keep track of document ids in the first collection? Does Firebase support any kind of "on insert/on delete" hook using cloud functions that can automatically maintain this second collection for me?
2
Answers
Not for the Firebase web and mobile SDKs. They always fetch the entire document any time it is matched in a query.
The backend SDKs allow you to specify which fields you want with
select()
. The exact expression will vary from language to language. Consult the API docs for more information.If you are using node.js, see:
This is a matter of opinion – there is no right answer. You should simply do that if you find that it helps your billing and performance requirements (basically, you should do the math to figure out if you’re helped by this). We can’t assess if this strategy is of any advantage for you without knowing your query patterns.
Look into Cloud Functions triggers for Firestore. You haven’t said if you’re using Firebase extension or not, so you should investigate which flavor is right for you.
https://firebase.google.com/docs/functions/firestore-events
https://cloud.google.com/functions/docs/calling/cloud-firestore
Here is a trick that is based on the use of the Firestore REST API.
When listing documents of a collection with the
listDocuments
method you can define which fields to return with a mask query parameter.The trick is the following: If you indicate in the mask a field that does not exist you receive for each document the following data:
name
(which is the path of the Firestore document),createTime
andupdateTime
.For example, below is the response of a call to the following URL (GET):
Response:
As you can see it is quite easy to exact the ids of the documents, since they are the last element of the paths.
Again, I’m not saying that is a perfect solution but it works in the sense that it returns less data compare to a query done through one of the client SDKs. You just have to issue an HTTP call instead of using one of the Client SDKs and you can very well use the two (i.e. HTTP calls and use of an SDK) in parallel.