how to synchronize Room data with Cloud Firestore? - firebase

I want to be sure that I can save data offline. How to synchronize data in Room with Firestore? When something inserted to Room Firestore must be updated as well.

Firestore already has a persistence layer included, you don't need Room at all. You can enable the offline support like this:
val settings = FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(true)
.build()
db.firestoreSettings = settings
Using Firestore for persistance has many benefits over Room (besides the saved effort and potential bugs). If you e.g. load all restaurants in a city, then go offline and then run a query on e.g. the best restaurants the query will still work and use the cached data even when the query was never run while being online.
You can also configure the cache size Firestore uses to meet your needs. Documents are cached in a LRU manner, so the documents which were not used for the longest time get removed from the cache first once it is full.
A best practice is to always use snapshot listeners. If you start a query in offline mode and the device gets back online, Firestore will automatically run the query again with the server and return the updated result to your UI.
Check out the docs and this video about Firestore offline mode for more details.

Related

Does Firestore not charge for documents that are cached and unchanged in a Read query with persistence enabled?

My assumption was that Firestore would not consider the client cache when evaluating Read usage. However, when I have persistence enabled in my application, it seems I can run the same queries endlessly and not see any change in my usage metrics. I've tested this over and over - when persistence is disabled, I see the usage metrics go up.
Given the amount of testing I've done, I feel that I should be able to safely declare that Firestore must be recognizing my local cache and only charging me for Reads on updated documents. However, I cannot find documentation around this anywhere, and I have combed through the docs. I'd certainly think if Google wasn't charging me for these cached Reads that they would want to highlight that benefit, whereas they really only highlight enablePersistence as an offline benefit - so I am perplexed.
Does someone have some insight into what is going on here?
Example enable persistence: firebase.firestore().enablePersistence()
Example query: myCollection.where(condition).get()
According to this documentation
Offline data persistence feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline
So, it is clear that you will only be charged when calling get() on the server to-read documents, mentioned in this answer
Also, be aware that
Offline Persistance is enabled by default for Android and iOS.
The pricing model for Cloud Firestore
This is a really great question. To clarify what the question is asking: "If my app is online and makes a query, but the query is fully returned by the offline cache, will I still be charged?"
I suspect yes.

Firestore Offline: Make sure a specific Document is always cached

Lets say I have a workout app, where every workout is one DocumentSnapshot. I want to have a donwload button, that downloads a workout/document.
I'm already using firestore's offline capabilities, but I need to ensure, that when I have downloaded this document, it is always available when opening the app without a connection.
So is it possible to ensure, that a specific document is always being cached in the local firestore cache?
I could also just persist the data of the DocumentSnapshot, the problem with this is, I can't update the Document and have the changes being synchronized with the "online" database when reconnecting with the wifi.
Is there any good way to achieve this?
So is it possible to ensure, that a specific document is always being cached in the local firestore cache?
It's not possible to ensure 100% of the time. The local cache is fully managed by the Firestore SDK. You don't have control over how it chooses to evict data from the cache. Any given cached document might be removed to make room for other documents in the future, if the cache becomes full.
Also, the cached document will not stay in sync with whatever is on the server, unless you write code to periodically query for (or listen for changes) in that document.
The functionality you're describing is best implemented with application code (probably with its own persistence layer) that specifically meets the needs of your app. The Firestore SDK won't do it for you.

Offline access to Firestore sub-collections

Looking for advice on my data structure in Firebase.
My app: Plant care reminders
I'm thinking the basic data structure can look something like this.
So the user can have many plants, and for each plant it can have many tasks.
I believe I would have a collection of users top level in Firestore, then each userData document would have a sub-collection of plants. Subsequently each plant would have a sub-collection of tasks.
The app will display all the users plants on one screen, that user can then click on a plant and view the tasks.
I would like the ability for the user to go offline for a period and still be able to access everything.
Is it wise to do one big query to retrieve all the data on the app load up? Doing this to make sure if they do go offline Firestore has all their cached sub-collections.
Or is it better to do a query on load up to get the users sub-collection of plants so they can see what they have, then when they click on a plant do another query to get that plants sub-collection of tasks?
If a user can see a plant, then goes offline and clicks that plant. Is it possible to query the plants sub-collection of tasks without network connection?
Apologies for poor explanation, trying to wrap my head round offline data persistence with Firestore and nested sub-collections when Firestore does shallow queries.
Firestore's disk persistence functions as a cache, maintaining data the app has recently loaded, and all local write operations that haven't been synchronized to the server yet.
I would like the ability for the user to go offline for a period and still be able to access everything.
This is inherently not a great match for how the Firestore disk cache works. To make it work in your use-case, you'd need to make sure to read all data, which will both drive up read operations and bandwidth consumption, and will also make the local cache runs more slowly than needed.
If you need a fully local database instead of a cache of recently read and locally modified data, Firestore might not be the best fit for this use-case. Consider using your own local database instead.

Does Firebase have a way to limit access to all public data in the security rules?

Update: Editing the question title/body based on the suggestion.
Firebase store makes everything that is publicly readable also publicly accessible to the browser with a script, so nothing stops any user from just saying db.get('collection') and saving all the data as theirs.
In more traditional db setup where an app's frontend is pulling data from backend, and the user would have to at least go through the extra trouble of tweaking the UI and then scraping the front end to pull more-and-more data (think Twitter load more button).
My question was whether it was possible to limit users from accessing the entire database in a click, while also keeping the data publicly available.
Old:
From what I understand, any user who can see data coming out of a Firebase datastore can also run a query to extract all of that data. That is not desirable when data itself is of any value, and yet Firebase is such an easy to use tool, it's great for pretty much everything else.
Is there a way, or a best practice, for how to structure the data or access rules s.t. users see the data, but can't just run a script to download all of it entirely?
Thanks!
Kato once implemented a simplistic rate limit for writes in Realtime Database security rules: Firebase rate limiting in security rules?. Something similar could be possible in Cloud Firestore rules. But this approach won't work for reads, since you can't update the timestamp at the same time the read is performed.
You can however limit what queries a user can perform on your database. For example, to limit them to reading 50 documents at a time:
allow list: if request.query.limit <= 50;

What's the difference between Cloud Firestore and the Firebase Realtime Database?

Google just released Cloud Firestore, their new Document Database for apps.
I have been reading the documentation but I don't see a lot of differences between Firestore and Firebase DB.
The main point is that Firestore uses documents and collections which allow the easy use of querying compared to Firebase, which is a traditional noSQL database with a JSON base.
I would like to know a bit more about their differences, or usages, or whether Firestore just came to replace Firebase DB?
I wrote an entire blog post all about this very question, and I recommend you check it out (or the official documentation) for a more complete answer.
But if you want the quick(-ish) summary, here it is:
Better querying and more structured data -- While the Realtime Database is just a giant JSON tree, Cloud Firestore is a little more structured. All your data consists of documents (which are basically key-value stores) and collections (which are collections of documents). Documents will also frequently point to subcollections, which contain other documents, which themselves can contain other documents, and so on.
This structured data helps you out in two ways. First, all queries are shallow, meaning that you can request a document without grabbing all the data underneath. This means you can keep your data stored hierarchically in a way that makes more sense to you without having to worry about keeping your database shallow. Second, you have more powerful queries. For instance, you can now query across multiple fields without having to create those "combo" fields that combine (and denormalize) data from other parts of your database. In some cases, Cloud Firestore will just run those queries directly, and in other cases, it will automatically create and maintain indexes for you.
Designed to Scale -- Cloud Firestore will be able to scale better than the Realtime Database. It's important to note that your queries scale to the size of your result set, not your data set. So searching will remain fast no matter how large your data set might become.
Easier manual fetching of data -- Like the Realtime Database, you can set up listeners in Cloud Firestore to stream in changes in real-time. But if you don't want that kind of behavior, and just want a simple "fetch my data" call, Cloud Firestore has that as well, and it's built in as a primary use case. (They're much better than the once calls in Realtime Database-land)
Multi region support -- This basically means more reliability, as your data is shared across multiple data centers at once. But you still have strong consistency, meaning you can always make a query and be assured that you're getting the latest version of your data.
Different pricing model -- While the Realtime Database primarily charges based on storage or network bandwidth, Cloud Firestore primarily charges based on the number of operations you perform. Will this be better, or worse? It depends on your app.
For powering a news app, turn-based multiplayer game, or something like your own version of Stack Overflow, Cloud Firestore will probably look pretty favorable from a pricing standpoint. For something like a real-time group drawing app where you're sending across multiple updates a second to multiple people, it probably will be more expensive than the Realtime Database.
Why you still might want the to use the Realtime Database -- It comes down to a few reasons.
That whole "it'll probably be cheaper for apps that make lots of frequent updates" thing I mentioned previously,
It's been around for a long time and has been battle tested by thousands of apps,
It's got better latency and when you need something with reliably low latency for a real-timey feel, the Realtime Database might work better.
For most new apps, we recommend you check out Cloud Firestore. But if you have an app that's already on the Realtime Database, I don't really recommend switching just for the sake of switching, unless you have a compelling reason to do so.
Reasons to choose Cloud Firestore over Realtime Database
It is an improved version
Firebase database was enough for basic applications. But it was not powerful enough to handle complex requirements. That is why Cloud Firestore is introduced. Here are some major changes.
The basic file structure is improved.
Offline support for the web client.
Supports more advanced querying.
Write and transaction operations are atomic.
Reliability and performance improvements
Scaling will be automatic.
Will be more secure.
Pricing
In Cloud Firestore, rates have lowered even though it charges primarily on operations performed in your database along with bandwidth and storage. You can set a daily spending limit too. Here is the complete details about billing.
Future plans of Google
When they discovered the flaws with Real-time Database, they created another product rather than improving the old one. Even though there are no reliable details revealing their current standings on Real-time Database, it is the time to start thinking that it is likely to be abandoned.
Suggest link from google as well :
Firebase Real-time Database vs FireStore
Extracted from google docs, a small sumamry here:
FireBase Real Time DB is JSON based NO SQL DB, meant for mobile apps, regional, and used typically to store and sync data between users/devices in realtime / extremely low latency.
FireStore is JSON 'like' NOSQL DB meant for high concurrency, global, easily auto scaling persistence, designed for any clients (not only mobile apps) with typical use cases such as asset tracking, real time analytics, building retail product catalogs, social user profile, gaming leaderboards, chat based applications etc.
Cloud Firestore is Firebase's database for mobile app
development. It builds on the successes of the Realtime Database with
a new, more intuitive data model. Cloud Firestore also features
richer, faster queries and scales further than the Realtime Database.
Realtime Database is Firebase's original database. It's an efficient,
low-latency solution for mobile apps that require synced states
across clients in realtime.
To choose between Firebase Realtime database and Cloud firestore based on your application requirements, read official documentation here.

Resources