Cloud Firestore multiple documents and unknown collection path - firebase

I am using Firestore database with real time updates on web javascript app.
The purpose is to show sensor data (temperature, ultrasonic, etc) for each existent device:
devices/devices01/sensors/sensor01/value:10
devices/devices01/sensors/sensor02/value:15
devices/devices02/sensors/sensor01/value:30
devices/devices03/sensors/sensor01/value:20
The user can have a list of devices it wants to get sensors data real-time updated.
users/userA/devices/{device01:true,device03:true}
users/userB/devices/{device02:true}
I don't know how to query and get the snapshots when:
1. Use device name from a list of devices
2. Get all sensors on change
Of course, this doesn't work:
db.collection("devices").doc("[device01,device03]").collection("pins").doc("*").get()
Any suggestion?

You need to identify each document individually and attach a listener to them all. There are no list-like or wildcard methods to refer to documents.
The only way you can listen to multiple documents at once is when you're able to identify them all with a query. The only kind of query that might help you here is one that identifies all the documents under pins. A CollectionReference is a query that listens to all the documents in that collection.

Related

Does a heavy document take much time in load from Firestore?

I am using both Firebase Database and Firestore in my app. I store users data like name, email, uid etc small details in documents of a collection as Users in firestore. It works perfectly. I made a node as Friends in firebase database to store friends list of a user. So whenever user open the app, it calls his information from Users from firestore and also his friends list from Friends from firebase database.
Now the thing is by this way it calls data from the Firestore and the Firebase database. So it means they are 2 requests/reads, one to Friends node and other to a document from Users collection. I think it would be better if i store friends list in Users document as an Array. So i will get only 1 read in Firestore. But i think that when the arrays of his friends list increases by 100+ elements. And also there are one or two more array lists like that. So will it take much time in retrieving a document from Users collection? or not? And which will be a better approach?
Here are the images of my current database structure as Users and Friends.
As per the Firestore usage and limits, the maximum size of a document is 1 MiB.
It means that as long as your user documents don't exceed the size limit, you can store friends data in arrays without a problem.
If you are planning to exceed the threshold, you may want to look for other options like creating subcollections to scale better as size of the subcollection doesn't affect the parent document's size in any way.
I built a chat app in flutter with firebase using mapping for each chat Text(only one doc was used in chat between 2 users). I observed that after I filled 1MB of data in doc, my mobile downloaded the chat history at 10-12 kbps from firebase.
Maybe the speed was a coincidence but I am sure that as your data grows in a single firestore doc, the mobile app does not bursty download the whole document simultaneously, instead it downloads at a much slower speed.
Please correct me If I am wrong.

Programmatically check Cloud firestore read/write count

Is there any way to check the read or write count depending on the call made by the code. For instance, let's say I have
final ref = Firestore.instance.document('users/uid');
ref.get();
Now that this is 1 read operation, and I can use
ref.delete()
or
ref.setData(data);
etc.
This is easy for single operations, how about I am listening for a Stream, how do I know how many read/write operations are taking place by my function calls?
It doesn't matter if it's a stream, or iterating an array, or any other form of consumption. Once the query hits the server, you are charged for the number of documents returned by that query, regardless of how you choose to iterate them. They show up in the client app all at the same time, and you get to choose how to deal with them.
For realtime listeners, you are charged a read for each document that gets delivered to your snapshot listener. Again, it doesn't matter what you do with the documents after that - the cost is already paid.

What is the best way to store a (potentially) huge list in Firestore?

I have a users collection with a bunch of users and their details. I also have a notifications collection, that the users can query on. I expect the amount of notifications to be at least in the thousands, but probably tens of thousands over the years.
I want the users to be able to mark a notification as "seen". How would I go about this?
I have considered following options:
Add an array notificationsSeen with references to notification documents to each user document. I'm scared of hitting size limits here though, if a user has seen e.g. 50k notifications.
Add the same but as a sub-collection in users. I'm not sure how to go about this though, since I only really need one property (notification ID). Do I put the notification ID as the sub-collection doc ID and have no fields on the documents? Do I let Firestore generate a random ID and assign the notification ID as a property on the sub-collection?
Add an array seenBy with references to user documents to each notification document. Although this will allow users to see which notifications other users have seen, and I don't think I want this.
Hope you can help me out, I'm out of ideas and I am not sure how to implement the best idea I have so far (sub-collection in users), which has also been mentioned as a solution here: Firestore storage size limit how to store large arrays (but without implementation details).
The only scalable way to store an arbitrarily large list of data in Firestore is using documents in a collection. Array type fields do not scale for growing lists of data because the items will eventually exceed the 1MB size limit for a single document, which will obviously cause problems at scale.
It's OK to have a document with no fields. If all you need to do is record that a document exists in order to check its existence later in that collection, that's fine. You can use the notification ID as the document ID if you are absolutely certain that ID conforms to valid IDs in Firestore. Otherwise, you should give it a random ID, and also put the notification ID as a field in the document so that you can query for it later.
You will want to familiarize yourself with the documentation on Firestore limits, which talks about the maximum size of a document, and also the valid characters for a Firestore document ID.
1st option is not possible, as document size limitation defined by firebase, 2nd and 3rd option are possible but 2nd option is a better to implement this feature, and in 2nd option i'll prefer to set notification id as the document id in the subcollection, but setting notification id as property in document is also valid(this option is better suited for case where there are multiple documents with same id, something like posts collection, where user has multiple posts posted).
It’s possible to build a collection for each user for their notifications. You may delete a user-specific document after the notification is read. You may also add some on_snapshot targets to send out notifications after it’s been added to the collection.

Create a collection linked to user ID in Firestore with flutter

Type of App to give context: An app that enables wedding bands to create a profile. Part of this profile will be to enter different dates with locations (Events)and return them in a list view. I have a Firestore collection called userData. The collection is made up of documents IDs(Firebase User ids) generated during sign in. These documents contain fields, mainly Strings and arraysfor things like a header image.I'm thinking of creating a class called Events with member variables date and venue. I'm wondering how I should structure Firestore to allow the Events be queried and returned in a listView. I've looked at sub collections where the UserData would be a parent but I'm not sure is this possible? Or maybe creating a collection at the root called Events but not sure how'd I'd connect the different bands to their Events. Here is a screen shot of Firestore. Each document is a band.
You can either:
Use a new top-level collection to store all events, with a field for the id of the band to help with querying for events for only that bad.
Use a subcollection under each band for their events.
It's totally up to you to choose. It will depend on the kinds of queries you want to make. Note that if you go with #2, you will not be able to query for events across bands (at least not until Firestore supports collection group queries which it does not today).

Does Firestore sync only diff?

I was wondering, how does Firestore handle real-time syncing of deeply nested objects? Specifically, does it only sync the diff?
For example, I have a state of the app which is just an array of 3 values and this state is synced between devices. If I then change one of the values will the whole new array be synced (transmitted on the network) or only the diff? What if my state is the nested object?
I'm asking because I want to sync the whole state which is an object with multiple fields but I don't wont to sync the whole object when I only change single field.
Like Realtime Database, Cloud Firestore uses data synchronization to update data on any connected device. However, it's also designed to make simple, one-time fetch queries efficiently.
Queries are indexed by default: Query performance is proportional to the size of your result set, not your data set.
Cloud Firestore will only send your device only the difference of the document.
Tips:
Add queries to limit the data that your listen operations return and use listeners that only download updates to data.
Place your listeners as far down the path as you can to limit the amount of data they sync. Your listeners should be close to the data you want them to get. Don't listen at the database root, as that results in downloads of your entire database.
Hope it helps!

Resources