2

Is there a simple way to structure a database that has messaging between two users. In firebase-database can you have to pointers to the same thing? I want to be able to make a pseudo clone of the conversation under both users. This way user1 has a list of people he is having a conversation with and so does user2 and the conversation information only needs to be stored once. I may have answered my own question as I am writing this, but these are two alternatives that I was considering. Block 2 seems significantly more space efficient. Does anyone have any other suggestions for how to approach this.

Block 1: Each time a message is sent stor it under both users.

{
    messaging:
        user1:
            user2:
                message1: 
                    messageBody: "text"
                    sender: "user1"
                message2: 
                    messageBody: "text"
                    sender: "user2"
                message3: 
                    messageBody: "text"
                    sender: "user1"
        user2:
            user1:
                message1: 
                    messageBody: "text"
                    sender: "user1"
                message2: 
                    messageBody: "text"
                    sender: "user2"
                message3: 
                    messageBody: "text"
                    sender: "user1"

}

or an alternative is Block2: Each time a message is sent store it under that conversation reference but have a reference to that conversation for each pair of users.

{
    conversations:
        conversation1:
            message1: 
                messageBody: "text"
                sender: "user1"
            message2: 
                messageBody: "text"
                sender: "user2"
            message3: 
                messageBody: "text"
                sender: "user1"
pairs:
    user2:
        user1:
            conversationName: "conversation1"
    user1:
        user2:
            conversationName: "conversation1"

}

Is there a way to say in the database, to say no matter the order of the children, point to the same thing? So that lines two and three would reference the same thing:

let dbRef = FIRDatabase.database().reference().child("messages")
let user1MessagesRef = dbRef.child("user1").child("user2")
let user2MessagesRef = dbRef.child("user1").child("user2")
  • I usually create unique room names by combining the UIDs or user names of the participants. See http://stackoverflow.com/questions/33540479/best-way-to-manage-chat-channels-in-firebase – Frank van Puffelen Nov 02 '17 at 15:01

1 Answers1

0

I am working on an open source chat app for iOS that uses Firebase, and I ran into that same problem.

My problem was that timestamps aren't being set to the same values, so I create a Firebase Cloud Function that clones the messages from the conversations to user data.

The way my database is laid out is as follow:

chats:
    chatID: (Which is both users' IDs separated by an '&' character)
        messages:
            childAutoID1:
                message: "message body"
                timestamp: server timestamp value.
                userID: the id of the user who sent the message
            childAutoID:
                message: "message body"
                timestamp: server timestamp value.
                userID: the id of the user who sent the message
userData:
    userID1:
        userID2:
            message: "Last message"
            timestamp: latest message timestamp
            userID: latest message user id
    userID2:
        userID1:
            message: "Last message"
            timestamp: latest message timestamp
            userID: latest message user id

At first, I was populating the messages to 3 places from the mobile app: chats/chatID/messages, userData/userID1/userID2, and to userData/userID2/userID1 But my problem is that they didn't get the same timestamp because there was a tiny delay between the times the values were populated to each node. So that's why I created the cloud function that copies the message from chats/chatID/messages to the other 2 locations.

Here's a link to the cloud function file: https://github.com/Tawa/TNChat/blob/master/Firebase/functions/index.js

Maybe it's not exactly what you need, but I hope it can help you solve your problem.

The project is still not documented, I'm planning on documenting it in the coming few days.

Edit: Forgot to mention that the cloud function also sends a silent notification to the recipient's device. Check the AppDelegate to see how that is also handled. :)

TawaNicolas
  • 636
  • 1
  • 5
  • 11
  • Hi TawaNicolas. Thanks for your response. In particular, though I was trying to see if there was a way to do this in a space saving fashion. For example in python when you do x={‘a’:1,’b’:2}; y=x; z={‘a’:1,’b’:2}; x and z point to completely different objects but x and y point to the same object so you only have 2 objects stored in memory and y just points to the same thing. – CentripetalA Nov 03 '17 at 12:37
  • What you did does bring up the option of using an ampersand to create unique chat mode between two users, though. If the usernames are unique and you put the two usernames in alphabetical order and concatenation with an & assuming usernames don’t have this character, then you can store the chat information once and find the key to the list of messages easily when you have the two users participating in the message. And the key will be consistent because you alphabetize the two usernames – CentripetalA Nov 03 '17 at 12:42
  • @CentripetalA I You can't point towards the same object in Firebase's database. They have to be written in different locations. However, as a space saver, You can do something which is already done but commented out in THChat: You can removes the messages once they're read. This is the best solution I could think of as a space saver, as I was thinking about saving space myself. But for now I disabled it. – TawaNicolas Nov 03 '17 at 12:44
  • @CentripetalA Usernames are phone numbers in TNChat, so they're unique, and there won't be the collision you're worried about. And you should do the same, don't use the username as the userID, figure out a unique key and use that instead. – TawaNicolas Nov 03 '17 at 12:45