There is a way to make less request in firebase?

Viewed 73

actually my firestore collection look like this:

user :
    |-> 0000 (uid)
        |-> avatar : 'url'
        |-> name : 'josh'
    |-> 1111
        |-> avatar : 'url'
        |-> name : 'steve'
    [...]

follow :
    |-> 0000
        |-> 1111 : true
        |-> 8888 : true
    [...]

message :
    |-> 0000
        |-> 8888
            |-> 1264978800 (timestamp)
                |-> message = "hello"
            |-> 1264978987 
                |-> message = "How are you"
    |-> 8888
        |-> 0000
            |-> 1264914253
                |-> message = "hey dude "
            |-> 1264975895 
                |-> message = "fine and you?"

If I want to get the profile and the conversation between 0000 and 8888 (to get they avatar for exemple), I need to:

  1. check if their friend
  2. if yes, get messages of 0000
  3. get messages of 8888
  4. get 0000 profile
  5. get 8888 profile

If I want a list of all conversation of 0000, I need to do:

  1. check all user to know if they're friend
  2. for each friend, get profile
  3. for each friend, get list of message.

This is very simple queries and this seem more heavy than in mysql for exemple.

There is a way to don't do all these queries? My database pattern is good?

Thanks for help.

1 Answers

It's time to think NoSQL with Firebase. Firestore is a real-time database where performance counts. Your data structure is good for a SQL database, not for NoSQL.

The following is the data structure I propose for this use case:

user :
    |-> 0000 :    //uid
        |-> id : '0000'
        |-> avatar : 'url'
        |-> name : 'josh'
        |-> follow : ['1111', '8888']    // Array of uid
    |-> 1111 :     //uid
        |-> id : '1111'
        |-> avatar : 'url'
        |-> name : 'steve'
        |-> follow : ['0000']    // Array of uid
    [...]

message :
    |-> AAAA    // message id
        |-> id : 'AAAA'
        |-> sender
            |-> id: '0000'
            |-> avatar: 'url'
            |-> name: 'josh'
        |-> receiver
            |-> id: '8888'
            |-> avatar: 'url'
            |-> name: 'paul'
        |-> time : 1264978800    // timestamp
        |-> message : "hello"
    |-> BBBB    // message id
        |-> id : 'BBBB'
        |-> sender
            |-> id: '8888'
            |-> avatar: 'url'
            |-> name: 'paul'
        |-> receiver
            |-> id: '0000'
            |-> avatar: 'url'
            |-> name: 'josh'
        |-> time : 1264978800    // timestamp
        |-> message : "hey dude"
    |-> CCCC    // message id
        |-> id : 'CCCC'
        |-> sender
            |-> id: '0000'
            |-> avatar: 'url'
            |-> name: 'josh'
        |-> receiver
            |-> id: '8888'
            |-> avatar: 'url'
            |-> name: 'paul'
        |-> time : 1264978800    // timestamp
        |-> message : "How are you"
    |-> DDDD    // message id
        |-> id : 'DDDD'
        |-> sender
            |-> id: '8888'
            |-> avatar: 'url'
            |-> name: 'paul'
        |-> receiver
            |-> id: '0000'
            |-> avatar: 'url'
            |-> name: 'josh'
        |-> time : 1264978800    // timestamp
        |-> message : "fine and you?"

The above structure is designed the NoSQL way. The profiles of users are duplicated multiple times. There is duplication of data to enhance performance and reduce bandwidth and CPU costs which are much costlier than storage.

Benefits:

  • Every user contains all information about user
  • Every message contains all information about message

Now, lets take your use cases:

If I want to get the profile and the conversation between 0000 and 8888 (to get they avatar for exemple), I need to:

  1. check if their friend
  2. if yes, get messages of 0000
  3. get messages of 8888
  4. get 0000 profile
  5. get 8888 profile

Query message where sender or receiver is in follow.

If I want a list of all conversation of 0000, I need to do:

  1. check all user to know if they're friend
  2. for each friend, get profile
  3. for each friend, get list of message.

Query message where sender or receiver is equal to '0000'

Other use cases you may incur:

  • List of friends with name and avatar to be listed.

You can use an array of map for follow to store uid, name and avatar or even make follow as a sub collection if you intend to do multiple operations on it.

  • User changes name or avatar.

Changes to name or avatar is generally less frequent compared to the number of messages sent and its real-time change may not be needed. You may create a cloud function to batch update all messages if it is needed to update all messages

Having said all this, it's clearly your choice to use SQL or NoSQL. Both have their own merits and demerits

Related