-1

Given the date model provided below, after a user logs in and retrieves their data, they can also get a list of their friends.

However, in order to now attain details of those two friends by ids fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de and a96da7b1-7c4e-44bc-b82e-fc75bed52bcd, at present, the most efficiently operation appears to simply be to loop through the urls, in such a way as:

for singleFriendID in allFriendIds

    firebase.com/[my_db_name]/users/{singleFriendID} 

end

but even that has its major limitations, if say you want a list of usernames of your 40 friends, you now need 40 individual, specific calls, to the server...

How can I efficiently lookup data within Firebase instead of dumping all the friend details to their phone?

Firebase schema:

{  
   "users":{  
      "99e4989b-a046-4c5f-9478-5ebd8bdc3ded":{  
         "email":"person@gmail.com",
         "friends":{  
            "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de":{  
               "confirmed":true,
               "selfSendRequest":false,
               "timeInvited":"2016-02-21 08:49:31"
            },
            "a96da7b1-7c4e-44bc-b82e-fc75bed52bcd":{  
               "confirmed":true,
               "seldSendRequest":false,
               "timeInvited":"2016-02-21 08:49:31"
            }
         },
         "password":"aPassword",
         "phoneNumber":"16144444444",
         "username":"person2"
      }
      "a96da7b1-7c4e-44bc-b82e-fc75bed52bcd": {
      ...
      ...
   }
}
Community
  • 1
  • 1
Sauron
  • 6,399
  • 14
  • 71
  • 136

2 Answers2

3

Loolooii's approach will save on the number of calls and is definitely a valid approach.

But you're also making the assumption that 40 calls to the Firebase database is a lot. If you take a moment to measure this, you'll probably be surprised.

In traditional databases, you do a roundtrip to the database for each call.

client                   server
    --- give me item 1 --->
                             loading
                             item 1
    <-- here is item 1 ----
    --- give me item 2 --->
                             loading
                             item 2
    <-- here is item 2 ----
    --- give me item 3 --->
                             loading
                             item 3
    <-- here is item 3 ----
    --- give me item 4 --->
                             loading
                             item 4
    <-- here is item 4 ----

Firebase pipelines all the requests. So essentially the clients immediately send the requests for all items in quick succession:

client                   server
    --- give me item 1 --->
    --- give me item 2 --->
    --- give me item 3 --->
    --- give me item 4 --->
                             loading
                             item 1
                             loading
                             item 2
                             loading
                             item 3
                             loading
                             item 4
    <-- here is item 1 ----
    <-- here is item 2 ----
    <-- here is item 3 ----
    <-- here is item 4 ----

You'll find that this is much faster, since you're only waiting for 1 roundtrip, plus the time to load the items. If that last bit is concerning, take Loolooii's approach.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thank you for clarifying the operational behavior. Is it possible, now instead of looping through the request, as I outlined within my question, but to "batch" those 40 requests? I ask because I need to possibly send several hundred to check if a users phone number contacts are linked to present users within the db. – Sauron Feb 22 '16 at 16:37
  • There is no difference between batching them and looping, aside from the number of "parentheses" it sends over the wire. – Frank van Puffelen Feb 22 '16 at 16:42
  • ok, then perhaps what it then boils down to is, what actions will occur more frequently. For example, a user changing their username, or pulling in a list of friends. Friends will happen multiple times a day. That said, I can easily create a "looping" update action if a user changes their information, but that is a VERY rare occurrence (I haven't changed my email in years...haha). By the way, I have seen you answer on several of my questions, and thank you for the support and patience. I am VERY new, (as of last Friday) to the NoSQL way of thinking. – Sauron Feb 22 '16 at 16:50
  • how can we calculate total data transferred? – Sauron Feb 22 '16 at 20:52
1

There is no need to do 40 calls to the db. You simply keep a list of friends per user (with each object containing every user info that you might need):

/users/:id:/friends

So when you want a list of your friends:

/users/:myId:/friends

Which will give you a list (with one call!), which you can loop through. So there is no need to do a separate call for every specific user endpoint.

There is no problem with having duplicate data in your db to improve performance!

Update (to answer the comment):

To show friends of a user or for example a list of people who have liked a photo, it usually suffices to only store IDs and names. To show more information, the profile of that particular user could be shown on click event.

Loolooii
  • 8,588
  • 14
  • 66
  • 90
  • But what if a user changes details about themselves, ie. Username. Don't you now need to update all locations of that username, all places where they are a friend? – Sauron Feb 22 '16 at 16:26
  • ok, then I should focus on what actions will occur more frequently. Changing a name/username is VERY rare in any app. Very quickly it becomes an identity that the user does not want to lose – Sauron Feb 22 '16 at 16:51
  • @Sauron most of the time the data you need about a user are data like username or name. This is for example the case when you want to show the names of people who have liked a photo or are friends of this particular user. In these cases it suffices to only store names for example and link to their profile if people want to see more data. – Loolooii Feb 22 '16 at 19:53
  • Yes, that is the conclusion that I attained from you and the answer below. Only allow duplicates on "high usage", like usernames, names, avatars, etc. – Sauron Feb 22 '16 at 19:55