Database Structure of One to One Chat App With Firebase

Photo by @rawpixel

Almost any mobile application that has to be built today has a part that requires an aspect of users communicating either in a group or a person to person chat.

Most at times, it is not quite easy to set up the database structure for such an application. When it comes to RDBMS systems such as MySQL, Oracle database or PostgreSQL, it is not much of a problem as such databases support data aggregation where with a single query, data can be queried from multiple tables and combined.

Well if you are new to mobile application development, setting up a backend on your own is not an easy task as you need the server to run 24h/7. Maybe you just want to try something new and see how it is.
That is where Google’s Firebase (firebase.google.com). It provides you with a mobile backend including file storage and crash reporting..

But How Do I structure the database

You have to first note that Firebase is a NoSQL database and as such, does not support data aggregation. Your database is simply a large JSON object

Users Node

When users sign up into a firebase application, each user is usually assigned a unique id. In this case, you will want to store the user’s information at a users node where each user is identified by their unique id. Using Firebase Firestore in this case, the structure will be something like this;

User’s collection

In the case of users, as shown above, using Firestore, there is a users collection and each user’s information is stored in a document identified by their user id. Firebase firestore consists of alternating collections and documents.

Same can be done with the Firebase Realtime database where users will be stored at a users endpoint with each user information stored at an endpoint identified by their id.

In this case, grabbing a particular user’s info to fill in their profile will not be a problem.A sample of how it is done with Kotlin is shown here.

val auth = FirebaseAuth.getInstance()
val myUid = auth.currentuser!!.uid
val userInfo = FirebaseFirestore.getInstance.collection("users").document(myUid)

Messages Node

The hardest part is deciding how the messages will be stored. One option that you might decide is that you store all messages at a messages node(with realtime database) or a messages collection(with firestore). In this case, all messages probably have an id and an author’s id.

But seriously, your application will crash if it gets large as querying will a particular user’s conversation requires you walking through the whole messages node.

Solution

Come to think of how Whatsapp person to person conversation works. When A starts conversing with B, a new thread is created for the two of them and so on. I almost found it impossible to do with Firebase until I got a hack.

In order to model such a structure, when person A starts a conversation with B, you compare their two ids(which are strings) and you append the greater id to the lower id. What do I mean.

If person A's id is 'aaabbb' and person B's id is 'eeeeeee', you create a thread between them with a node 'aaabbbeeeeeee' and all their messages are stored at that node. In this case, when loading conversations between the two, say in a list, you query just that endpoint. An example of setting user endpoint is shown below
/**Function setsup endpoint for one to one chat**/
private String setOneToOneChat(String uid1, String uid2)
{
//Check if user1’s id is less than user2's
if(uid1 <uid2){
return uid1+uid2;  
}
else{
return uid2+uid1;
}

}

With this structure, you are sure of always starting a new thread between any pair of users.

If you need a good mobile or web backend for a start, Firebase is indeed a good choice. Firestore is more preferable to the realtime database but it is still in beta mode. Do well to check their differences and make a choice