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.
Related
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
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 a product listing that when clicked asks the viewer(user viewing the product) if they would like more information.
If yes then it takes them to a chat interface which the viewer can then send a message to the product author (user who the post belongs to).
The app takes these two users id's and hashes it and combines them to make a single string that is used as the document id for the chat interaction, that way both users read & write from one collection.
Now there is a messages tab in the app and there I would like to get all the chats(interaction between userA and userB) where each of the two users are apart of. So that later on they can go to the messages screen and continue messaging. Is there a way to achieve this?
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 am developing a Firebase chat app.
I have implemented Firebase email/password authentication. So, when user signups successfully, I have a code through which on every signup/register the app stores user details like name,email, etc in Firebase database under uid node.
Then, the user searches for a friend using a email id,
if the uid with that email id is present in the firebase database, the function returns true,
then, the app, adds that email id under
<FirebaseApp>
<users>
....users details...
<friends>
<userid>
<unique pushed id> : searched email // here the friend's email id is added
After adding the new friend,
I am using a recyclerview to show the friend list.
So, the app retrieves all the nodes under friends>> current user's uid>>
As my database structure describes I have only saved friends uid in friends database.
At first step the user will have only friends' email ids. Let say in List friendsList.
Then I use this friendsList to retrieve all the other details of friends like profile picture, name, contact and etc... which is saved under users node.
But using for each loop retrieving the other details of every friend, and then store in a array list, then paasing that arrayList to adapter and then displaying to recyclerview. is a very time consuming process.
Becuase, it can have other functions too. like converting Base64 image to bitmap etc.
So every time activity starts , following all above steps, will make a lengthy process.
other that this, I have another way, where I can save friends other's details too under friends node. like name, contact etc. at a point when a new friend added to the database.
But again another question arises.
yes, I can store friend's other details too... But what if the friend updates his profile picture, contact?
So, this procedure is not suitable in my case.
How can I create a whatsapp like friends list in my Firebase app, where I every user's friends list will be always updated with his/her friends details.
also, the will not go under any lengthy process.
The best approach is to save all the necessary details in the friends node as well.
You can just save the Opposite_Friends tag in each user, where just add all the uids in whose friends list user is present, So that whenever user updates any detail, you can update it in every users Friends node as well.