I am working on a chat app where messages store in firebase realtime database. Now if i make a node shown below ( chats-Between-A-and-B-Id are autogenerated chatroom keys ), so i want to know that when user S open chats with user T in chat app so Database will read only the messages stored in chats-Between-S-and-T-Id and will not read others chatroom messages !? am i right ? if yes then will it reduce the pricing?
chats-
chats-Between-A-and-B-Id-
messageID1-…
messageID2-…
messageID3-…
...
chats-Between-o-and-p-Id-…
chats-Between-s-and-t-Id-…
chats-Between-x-and-y-Id-…
OR
If i store data like shown below then if user S open chats of user T in chat app so Database will read whole messages and
cahts-
messageID1-…
messageID2-…
messageID3-…
...
sort them like (shown below) so it will read all messages and sort them and show in app to the user !? which will increase the pricing ?
if(chat.getReceiver() == senderID && chat.getSender() == receiverId ||
chat.getReceiver() == receiverId && chat.getSender() == senderID)
{
(mChatList as ArrayList<Chat>).add(chat) //show chats
}
I want to know which approach can save my money.
Edit
I am using the 2nd approach (i got it from a chat app tutorial). Where we sort messages according to senders and receiver but after reading the answer of #sharath i get that if i go with this it will read every message from chat node and then sort them according to sender-reciver and if there are 1 million messages from all the users then it will read 1 million messages and sort only some of them only for 2 users! It will make me poor. So i am thinking about using the 1st approach where i will get messages from chat>>roomIdBetween2Users so it will ont read others chat and give me secure, maintainable and affordable databse.
And this is the image of my database here chats is parent node contains all the messages of all the users and sort them as i mentioned in the code for 2 users. There are already approximately 500+ messages in chats. And it will be so dangerous in future.
Its a little tricky situation to answer this without knowing your firebase DB structure. Am making an assumption and generalising this answer.
Firebase is a No SQL Database which stores data in tree structure or Parent child manner
Main important logic you should think of while developing anything with NoSQL databases are you need to create the Firebase DatabaseReference to the deepest node possible. Firebase queries and reads data which comes under the referenced node.
For example : if you have firebase structure as below
See this image of Firebase sample structure
If you want to access chats of User S, Create Reference to ID_User_S node.
note: If you create reference top node "Chats" then snapshot returns all child information under it
Regarding pricing : Yes the lesser the data you read lesser the price you pay. If you are referencing to deepest node possible you read lesser data. Try to optimise all firebase queries to reach to deepest node possible for creating a reference.
Now coming to your structure
chats-
chats-Between-A-and-B-Id-
messageID1-…
messageID2-…
messageID3-…
...
chats-Between-o-and-p-Id-…
chats-Between-s-and-t-Id-…
chats-Between-x-and-y-Id-…
If you create a database reference to Chats node then each one trying to access the chat will read every child under it which includes others chats as well.
So for efficient usage create reference to chats-Between-A-and-B-Id- so that you can get exact list of messages under those 2 users
Related
Following is the schema of my Firebase Realtime Database:
Chats node
chats
chatId
chatId
adminUserId
chatSubject
chatIconUrl
chatCretionDate
lastUpdated
User chats node
user_chats
userId
chatId: true
What I want to do:
What I want to do is to present a list of all chats a user is subscribed to in the ChatListFragment of my app and observe it for changes, e.g., new chat added, any chat removed, a change in chatSubject, chatIconUrl, lastUpdated etc.
What I have done:
Since I've already denormalized the data, the first step would be to retrieve a list of chat ids a given user is subscribed to, and this I can very easily achieve as follows:
FirebaseDatabase.getInstance().getReference("user_chats").child(userId).addValueEventListener()
Next task is to get the complete chat data from chats node against each of the chat ids retrieved above.
I know that I can't write a query to achieve this because the retrieved chat ids are a random subset out of the hundreds or thousands of total chat ids.
So, I loop through the retrieved chat ids and fire a query for each as follows and collect the retrieved Chat (A POJO that maps to the fields in chats node) object one by one in an ArrayList:
FirebaseDatabase.getInstance().getReference("chats").child(chatId).addValueEventListener()
Here, I've to ensure completeness of data by matching the size of ArrayList<Chat> with the size of chat ids retrieved from user_chats node. When both sizes are equal, I supply the ArrayList<Chat> to the ListAdapter.
BUT, in addition to above, I also have to deal with the following:
See why onDataChanged() of the listener attached to each chat id has been called: to supply a new chat snapshot or report changes in an already supplied chat snapshot.
Remove listener associated with a chat id that the given user is no longer subscribed to.
This becomes even more complicated when I try to do it all in a ViewModel using LiveData.
Here are my questions:
Do I really have to go through such a trouble just to compile a list of chats that a user is subscribed to? This is supposed to be the first screen of my app and I can't happen to get past it.
Is there a standard / better way to achieve my objective with the same data structure?
Do I need to make further changes in my data structure to achieve my objective? What I'm thinking is to expand the user_chats node by adding the same fields that chatsnode has. That seems pretty weird though because, first, if there are lets say, 500 members in a chat, there would be 500 ditto copies of the chat in user_chats node and second, in case of any update in data, I would be updating the chat info in chats node and then all the 500 copies in user_chats node. That would be ridiculous when we think about how frequently the lastUpdated field would be updated.
Any help would be really appreciated!
how to know when all the queries get completed.
One common way to do this is to count them. Since you know how many chat IDs are under /user_chats/$uid, you know how many nodes you have to load from under /chats. Each time you get the first result for one of these nodes, you increment a counter. When the number of chats you've loaded is equal to the number of chat IDs for the user, you're done.
I have created a game in which, the android app have the chat feature, not i'm storing every single chat text in a
child node not that chat node has been created more that 1000 times because of chatting, now i want to delete all the message nodes or say want to provide delete chat feature in my app, what should i do to remove all chat nodes.Here's my realtime database reference
i have tried this methods
This method didn't work
this also didn't work
i don't know why i did this but yeah this worked but for less node if i have 10 or 20 sms its works, but if i tried to delete chat with 1000 sms it shows error like "This request would cause to many function to be triggered"
i want to delete all the sms nodes which have more node like 1000 or so.
Just set the chat user node you want to delete to 'null'. Something like:
mRootRef.child("messages").child(<current_user_node id>).child(<chat_user_node id>).set(null)
I have an Android app that uses the Firebase Realtime Database. At the moment it is a single user app, in that when a user logs in, using Firebase Auth, the data they create is kept private to them. What I need to do for the next phase of the project is to allow for the creation of teams or user-groups that have access (read and write) to the data currently created by a single user.
The database structure and rules for doing this are understood, however, the issue I have is how to create the groups.
I did find the following blog and it is very close to what I need, it does not make clear how a new user would create the pending membership entry in a specific "chat" (this is a group chat sample).
https://firebase.googleblog.com/2016/10/group-security-in-firebase-database.html
Any points on resolving this final issue would be much appreciated.
Sid
Just simply create groups like below
|--Groups
|---group1
|-----uID1 - owner
|-----uID2 - participant
|-----uID3 - participant
..............
follow this https://firebase.googleblog.com/2016/10/group-security-in-firebase-database.html link. There are example groups and rules. It will help for u to proceeds it.
Follow this https://firebase.google.com/docs/database/ios/structure-data to make good structure of data to increase performance
I have problem with restructurizing my database.
So far I have different users storing measurement data. Keys are made of (userId+currentDate). But now I'd like to add sharing this data between users.
Users can send requests for permission to view each other data, but I don't really know where should I store this data.Should I add additional key(userId) with value (true) inside each node? Can I even update the database in such way - "If user1 is friend with user2, add user1:true to each of users2's nodes"?
How should I proceed?
You can create a second type of node, something like shared_with_me_<my_user_id> for the user requesting access to another user data. If agreed by him, you insert this user_id to that node (like <other_user_id>:true) so you can query it later.
That said, I really suggest that you start using the Cloud Firestore Database.
I'm creating an application that uses Private chats to let people communicate.
I have 2 trees. One contains all the messages, and the other contains details about every chat. (necessary to show it on "My chats" activity without loading the whole messages tree).
My structure is:
Each privatechatdetails key contains uid1 & uid2, lastMessage node with details about the last message that has sent, and 'users' node that contains 2 users details, keys are the uids.
I want to show each user only the chats that he's in. How can I achieve that using Firebase Rules?
For now I'm using orderByChild & equalTo trick -
mFirebaseDatabaseReference.child("privateChatsDetails").orderByChild("users/" + mUid + "/chat").equalTo(true)
Working perfectly, but I want to order the list by last message timestamp, so I need to do that user chats check using Firebase Database Security Rules.
Thanks in advance.