I need some help designing the Firestore database for my app. The app has three requirements:
Display documents in a recycler view;
The user to rearrange document items via drag and drop; and
Multiple users to access the documents and independently rearrange their items.
The first requirement is straight forward using a Firestore query.
The second requirement I’m planning to have a “position” field in the documents so the query can be “ordered by” the “position” field.
It’s the third requirement where I have difficulties. My first thought is to is to have multiple “position” fields associated with each user and order the query by the “user’s position” field. However, since Firestore requires an index for each query this approach does not work.
Any suggestions as to how best to design my Firestore database to accomplish the app’s three requirements would be appreciated.
You could store each user's ordering in a per-user document or collection (organized separately from the data itself). Simply map each document id to that user's chosen position for it. This means you would also need a separate query to get that ordering, but you wouldn't need a new index at all.
For anyone else that is interested, below describes my changes:
Excluded the “position” field from the Firestore item document. So, now when item documents are retrieved from Firestore they contain no position information. And they are downloaded in no particular order.
I’ve created a new Firestore “state” document that has a “positions” field that is a map with its key as the item’s uid and a position Int as its value. (I’ve also included an Int field that holds the recycler view’s firstVisiblePosition and another that holds its offsetTop so the recycler view can be restored to its last position.)
After the initial loading of item documents, the position values are applied to each item document. And the item documents are sorted by their position.
I handle ADDED, MODIFIED, and REMOVED document change events in my recycler view’s adapter. The change events “oldIndex” and “newIndex” values are not used.
Last, I save the “state” document under a user’s subCollection in the onStop lifecycle call back.
Hope this helps.
Related
From the context of a todo application, the user has a list of todos, if they reorder an item anywhere in the list how could that be saved in Firebase Firestore?
I currently have a collection with ALL todos. They get filtered by user ID and day, but I’d like to allow for custom ordering of todos. How could that be achieved?
In order to maintain the previous costs while also allowing todo items to be ordered per user you can utilize a new field per document in the todo collection. You can attempt to add a field, named lets say "order", which will hold the numerical value for the order of the todo element for each user. For example "0" for first position,"1" for second, and so on so forth. These will then be filtered by user ID and day as mentioned previously.
There is no inbuilt solution available for this. The solution I will suggest is to keep a separate document per user which maintains the order of documents (in this case to do items) in an array and when you show the data to the user in the UI, use the document to order the items on the page.
But keep in mind this approach will increase your database costs because you will need to perform an update to 2 documents whenever a new todo is created.
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.
So i have a collection named products in my Firestore and it contains all my products.
Since i am using Tag widget it gives me an error when there is more than one item sharing the same tag. So for my Products Builder i want to give a list that contains all my products without a specific product catched by his id, so stream property of my Stream Builder can be like this.
StreamBuilder(stream: Firestore.instance.collection('products').WITHOUT SPECIFIC PRODUCT ID .snapshot()
builder:...)
How can i do that?
It's not possible to construct a query for all documents except one. There are no inequality filters in Firestore.
Since it's just one document, it makes sense to simply do the query for all documents, the have the client code remove the one you don't want from the result set.
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.
I'm adding data to cloud Firestore through the Firebase Console. I've added a collection and the corresponding documents and fields. When I click on " ADD DOCUMENT", the new document appears randomly (as far as I can make out) on the document column. I want the newly generated document to appear at the bottom of the document column. The order matters when viewing the data on the app. The data is used in a recycler view. Is this possible?
Cloud Firestore does not order documents in the same way as the RTDB. Auto IDs are not time related. You will need to add a timestamp field and order your data by this field.
You can read about this here.
Important: Unlike "push IDs" in the Firebase Realtime Database, Cloud
Firestore auto-generated IDs do not provide any automatic ordering. If
you want to be able to order your documents by creation date, you
should store a timestamp as a field in the documents.
I used Firestore's "set" method instead of "add" and used a numerical date string; it is automatically adding and listing them in numerical order.
// Swift
let dataToSave: [String: Any] = ["example": "example"]
collectionRef.document(dateString).setData(dataToSave) { (error) in
}
If you use the "add" method, the key will be automatically generated with a random alphanumeric string.
The collection orders everthing alphanumerically, so setting your documents using keys of numbers or letters, exclusively, will allow for an ordered list.