Querying on Firebase or on the client - firebase

Basically I have a set a of data on my website and on I have some checkboxes where the user can check to filter the data. The data will be 40 items per page. Should I query my data in firebase or when I get the data back from firebase. The reason I'm asking is because the user can check and uncheck the checkboxes which means every time the users the users does that I'm getting charged, since firebase charges by use by at the end I want to make sure I follow the best practices.
The queries will have OR. I know in firebase there's not such a thing as an OR when querying but I found a workaround
https://medium.com/google-developer-experts/performing-or-queries-in-firebase-cloud-firestore-for-javascript-with-rxjs-c361671b201e

Related

Firestore model for fetching a list of friends of an user

I have been using Firestore for a very long time. I am building an app now where scalability and keeping low costs is important. (I am using flutter)
My app has users, which have user profiles, also they can add friends and talk to them (like instagram or facebook).
I have a problem building this friends system.
My model for this friends system currently looks like this:
Users collection. Each document id = user id from auth, those docs contain data like name, username, profile picture, etc.
Friends collection. Each document id = user id from auth. For each user, those docs contain a field called: friends, which is an array with each of his friends user ids.
The model looks like:
Friends collection:
- uid:
- friends_list: [friend_uid1, friend_uid2, ...]
This is how my "backend" looks.
Now I want to show my user a list of his friends. How do I do that?
I want a list that looks like instagram, with a nice UI showing each of my user friend profile pic, name, last message, etc.
I can not find a straight forward way to do this with Firestore and queries.
Let's say I do it like this:
Get all my friends user ids in an array.
Get all their user documents using .get() for each document.
This is not doable in firestore cause it would eliminate all the querying power I have (such being able to query only for users with name "x"), I would have to fetch all users and do the query on my front-end (or in a cloud function, same thing, not scalable).
If I do this like:
Get all document using a query for all users in the Friends collection, where friends_list contains my user id.
Save from those documents only the documentID and fetch all the friends user data manually.
This comes with another problem. In Firestore there is no way of fetching a document without fetching all of its fields, so the first query which I use to get the ids only of my friends would actually give me their id + their friend list instead (cause when I query, it also gets the document id + the data), which is not good.
If I do it like:
When you add a friend, instead of just saving its uid, save its uid + data.
Now I can easily show my user his friends list nicely and do some querying on front-end.
The problem here is that now if one of my friends updates his profile photo, I need to update it in every document of all of his friends, which is very write expensive for just a little profile update.
There is also the problem of watching for more data, maybe I have another collection with Chats, and I want to show the last message of my chat with a friend, now I have to fetch the chat rooms too, which is more hard to query data that comes with all the problems that I mentioned before.
In conclusion: I don't see a good scalable way to do this kind of system within Firestore. It seems a simple system which any basic app should have, but I do not see how I can do it in a way that does not make lots of reads or read more data (or sensitive data) than it should.
What kind of model would you do for a friends system like this?
You're decribing a quintessential drawback of NoSQL Databases.
A similar example is actually given in the Get to Know Cloud Firestore series.
Like others have commented, the answer really depends on your application. And this is the assessment you'll have to do. Like which of the options is cheaper depending on the use case of the app.
For example, if you go with your third option and store the friend's user data that you'll need to populate the list. This means you'll have to implement measures to keep the integrity of the copied data whenever the user updates their information.
You can then look at the usage of your app and determine how often users change their information vs how often you would need to retrieve full users if you don't copy the data to find the cheapest method for your application.

Strange Firestore console situation

I have a small database in Firebase realtime database which contains posts added by users. Everytime I open the console, each and every post is in the correct position.
I'm trying to migrate to Cloud Firestore. I've created a script to copy every post objects from Firebase realtime database to Cloud Firestore and works fine.
The problem is when I switch the tab to Firestore, the posts are not ordered anymore and I find hard time to find a post.
How can I order the posts in the exact same way that were in Firebase and also in the ListView?
Strange Firestore console situation
It is not strange, is the normal sorting scheme provided (by default) in Firebase console.
Unlike the Fireabse realtime database ids, Cloud Firestore ids are actually purely random. There's no time component included. That is why (by default) there is no order. However, as Frank van Puffelen mentioned in his comment:
The Cloud Firestore console support sorting/filtering of the documents on any field (since June 2018), by clicking the "filter" icon above the document list.
Beside that, if know the id of a document, just simply CTRL + F in your browser and you'll be able to find the desired document very easy. In my opinion, this sorting scheme makes it relatively intuitive to find the document you might be looking for.
If you want to order your elements in your ListView, you should add those requirements into queries. The order in your query is not related with order you see in the dashboard.
Those ids are required so an app like yours can work perfectly on a big scale. At a big scale, it doesn't matter what order the documents appear in the console because the console is useless for viewing large amounts of documents.
A solution for ordering your posts in the ListView, would be to order your posts according to a timestamp property.
For Android, here you can find how to add the date using a model class or FieldValue.serverTimestamp().

Checking for New Entries in Firestore - Local Storage

So I have a Firestore database where i have all my posts in, I push them on page load into the store so I can have a fast navigation and only need to fetch once.
What I wanna do now is to use a persisted state so i dont need to refetch it if the user opens a new window or F5(reloads) the page.
The problem is im not sure how to check if new Posts are in the Firestore without querying all posts and I havent found any methods to do it in a healthy and Read efficient way.
There's no super easy way around it - at the end you have some data, and the server has another, you need to check for differences.
If you're only trying to figure out if there are new posts on the backend, which are not loaded on your frontend, then just get the date on your last post, and then ask Firebase for all posts after this date :)
Of course if you don't have posts, ask for everything.
Keep in mind you need to manually check if posts are deleted ;)
Realtime updates with the onSnapshot method can be used to keep local data in sync with the server. If you initially load it into vuex then subsequent changes on server side will be reflected automatically.
https://firebase.google.com/docs/firestore/query-data/listen
To share one set of data across tabs/windows you could look at something like this
https://github.com/xanf/vuex-shared-mutations

Firebase's KeepSynced and persistenceEnabled

I'm using Firebase's KeepSynced and persistenceEnabled but i don't understand it completely.
I have 2 questions -
What do this functions do exactly? I understand that they connected to cache and offline logic but why do i need them both?
I have a list of categories, and after the user choose a category i show a list of all groups related to this category.
I'm using firebase database.
How can i create cache for the groups, but at the same time refresh the group list after the user choose category? Is it possible to only refresh the data that is missing from the cache?
thanks for the help.

Automatically Updating Stale Data in Firebase

I have a social networking structure in my Firebase Database that provides a user following system
user-followers
-F2iRZkwfuTcKUvd7uYD0jwWeJ7T2
-KgkkWy5xesvcFcL9GMh:
-username: 'billybob'
-fullName: 'Billy Robertson'
-KgkoZpD0GP687J_5Zh5: true
-username: 'coolguy55'
-fullName: 'Jim Davis'
This works fine for reading a summarized view of a given user's followers. However, when a user updates their profile, say their username or fullName, the data under user-followers immediately becomes outdated.
Is there any feasible solution to keeping this nested data updated, without writing an extra function when a user's profile is updated? To me this seems unavoidable
Any input is appreciated!
You could use Cloud Functions for Firebase to write a database trigger that runs in response to writes that happen in one place in your database so that other changes can be made to keep things consistent where data needs to be duplicated.

Resources