How to turn off automatic indexes in firestore for subcollection - firebase

I don't want to have automatic indexes created by firestore because I need to remove and add every five minutes 50-100 documents (each doc has +/-60 fields) to my subcollection. This causes of big volume for "Cloud Firestore Index Write Ops" (300k / day for only one user) and Cloud Storage. I don't need to sort, filtering that documents so I suppose I can turn off automatic indexes, right?
I know that I can add exemptions for fields, but I don't know how can I use it for documents in subcollections. What should I pass in Collection ID and Field path if the path for documents is like:
mainCollectionName/{id}/subcollectionName/{document=**}
and when should I select a collection checkbox and when collection group checkbox?

Unfortunately, it's not possible to disable indexes or create exemptions for documents to be indexed. As clarified in this similar post here, this cannot be achieved and there is even a limit of 200 exemptions of fields that can be done - you can check the limits here.
For your case, indeed, you would have to exempt the fields individually and besides that, to create the exemption, to set the collection you use its id and not the path. So, you would only need to set in the Collection ID field the subcollectionName and then the field to be exempted.
In addition to this, feel free to raise a Feature Request in Google's Issue Tracker, so they can check about implementing an exemption of documents in the future.

Related

Query only specific field with firestore

I use this code to get a collection snapshot from Firestore.
firestore().collection('project').where('userID', '==', authStore.uid).onSnapshot(onResult, onError);
This returns a huge amount of data, but I only need a few fields. Is it possible to query only a specific field? For example, if I only need the projectName and the creationDate fields.
Is it possible to query only a specific field?
No, that is not possbile. A Firestore listener fires on the document level. This means that you'll always get the entire document.
For example if I only need the projectName and the creationDate fields.
You cannot only get the value of a specific set of fields. It's the entire document or nothing. If you, however, only need to read those values and nothing more, then you should consider storing them in a separate document. This practice is called denormalization, and it's a common practice when it comes to NoSQL databases.
You might also take into consideration using the Firebase Realtime Database, for the duplicated data.

Can I reuse existing fields as Sharded timestamps in Firestore?

I was looking for a solution to Firestore's limitation of Sequential indexed fields which means the following from this doc.
"Sequential indexed fields" means any collection of documents that
contains a monotonically increasing or decreasing indexed field. In
many cases, this means a timestamp field, but any monotonically
increasing or decreasing field value can trigger the write limit of
500 writes per second.
As per the solution, I can add a shard field in my collection which will contain random value and create a composite index with the timestamp. I am trying to achieve this with the existing fields I have in my Document.
My document has the following fields:
{
users: string[],
createdDate: Firebase Timestamp
....
}
I already have a composite index created: users Arrays createdDate Descending. Also, I have created Exemptions for the fields field from Automatic index settings. The users field will contain a list of firebase auto-generated IDs so definitely its random. Now I am not sure whether the field users will do the job of field shard form the example doc. In this way we can avoid adding a new field and still increase the write rate. Can someone please help me with this?
While I don't have specific experience that says what you're trying to do definitely will or will not work the way you expect, I would assume that it works, based on the fact that the documentation says (emphasis mine):
Add a shard field alongside the timestamp field. Use 1..n distinct values for the shard field. This raises the write limit for the collection to 500*n, but you must aggregate n queries.
If each users array contains different and essentially random user IDs, then the array field values would be considered "distinct" (as two arrays are only equal if their elements are all equal to each other), and therefore suitable for sharding.

Is it possible to exclude field on firestore index?

I just watched the playlist of Get to know Cloud Firestore, and I just learned that every field of the document is indexed.
My question is, is there way for a certain fields to be excluded on by Firestore indexing? Something like fields that I am pretty sure that I will not be using as a query lookup.
Thanks.
As you correctly found, Firestore automatically indexes all individual fields of the documents in the collection. You can exclude certain fields from the single field indexes panel in the Firebase console.
From there:
Cloud Firestore creates the indexes defined by your automatic index settings for each field you add, enabling most simple queries by default. You can add exemptions to manually set how a specific field is indexed.
From there, you can enter the collection (or collection group), and the field name, and then select which indexes (ascending, descending, arrays) get auto-created or not.

Correlating Firestore indexes to slugs in a webapp

I'd like my web app router slugs to correspond to my Firestore documents data.
For example:
www.mysite.com/restaurants/burger-king
/restaurants <- Firestore Collection
/restaurants/mcdonalds <- Firestore Document
/restaurants/burger-king <- Firestore Document
This is easy enough, as I can assign the name as a slug-friendly UID in Firestore. The difficulty arises with CRUD functionality. I need to be able to rename my item titles, but Firestore does not permit you to rename indexes, which is the issue I'm facing.
One SO solution I saw was to delete the old record and creates a new one at the updated index. That's problematic for me, because sub-collections would be hard to transfer from the client side.
Are there more elegant solutions?
You don't have to identify a document by its ID. If you're able to ensure uniqueness of a document field value, you could instead query a collection for an ID value in a known field, then use the results of that query to satisfy your REST API. Then, you can change the value of that document field as often as you want, in order to satisfy required changes to the public API.

Multitenancy in Firestore

Regarding the actual limitations in querying data based on subcollections values, what is the suggested way to manage multitenancy in Firestore?
I would like to be able to retrieve and limit access to data related to entities/companies the user is part of.
Example data structure :
/companies/{companyId}/users/
/companies/{companyId}/users/{user}/roles
/companies/{companyId}/docs/
Can /companies/{companyId}/users/ be a collection?
How can I only retrieve companies where user own a role in /companies/{companyId}/users ?
Firestore paths alternate from collection to document and back again:
/collection/document/subcollection/subdocument
So yes, in this case, you would have collections of companies, users, and docs. Collections are also implicit in that they are created automatically when documents exist in them, and removed when no documents exist in them.
At present, subcollection queries (e.g. "all users in a given company") aren't supported, so you'll have to structure your query the other way around: having a users collection with company as a property, when performing a query to find all users in that company.
ref.collection('users').where('company', '==', 'ACME').get().then((document) => {/* Do stuff here */});

Resources