0

Assuming I have the following firebase structure

{
  "users":{
    "user1":{
        "username":"john",
        "full_name":"John Vincent",
        "created_at":"9th Feb 2015",
        "groups":{
            "group1":true,
            "group3":true
        }
        "last_logins":...
    },
    "user2": ...,
    "user3": ...
  }
  "groups": {
     "group1"{
        "group_name":"Administrators",
        "group_description":"Users who can do anything!",
        "no_of_users":2,
        "members":{
            "user1":true,
            "user3":true
        }
      },
     "group2"{
        "group_name":"Moderators",
        "group_description":"Users who can only moderate!",
        "no_of_users":1,
        "members":{
            "user2":true
        }
      }
   }
 }

Now if i want to get a list of users in group 1, it would be easy, but how do i get a list of users in group 1 with their username, full_name etc? do i have to get a list of ids first and then do a foreach to get each individual user info and then add them to an array? I assume there must be a better way.

For example: If i click on a group, I want to show a list of users with their full_name displayed first, so I modified the above structure:

{
  "users":{
    "user1":{
        "username":"john",
        "full_name":"John Vincent",
        "created_at":"9th Feb 2015",
        "groups":{
            "group1":true,
            "group3":true
        }
        "last_logins":...
    },
    "user2": ...,
    "user3": ...
  }
  "groups": {
     "group1"{
        "group_name":"Administrators",
        "group_description":"Users who can do anything!",
        "no_of_users":2,
        "members":{
            "user1": {
               "full_name":"John Vincent"
            }
            "user3": {
               "full_name":"John Doe"
            }
        }
      },
     "group2"{
        "group_name":"Moderators",
        "group_description":"Users who can only moderate!",
        "no_of_users":1,
        "members":{
            "user1": {
               "full_name":"John Vincent"
            }
        }
      }
   }
 }

Now full_name is duplicated at 3 different places for user1, possibly even more depending on how many groups he's in, how do I then do a firebase multi-location update? I've read about multi-location update online, it seems the ending "id" for the multi-location update needs to be the same. In the above case, if i update user1 full_name, how do i update it inside different groups too???

UPDATE

Based on Frank's answer:

In your code a simple multi-location update would write these locations:

"/users/user1/full_name": "New Name",
"/groups/group1/members/user1/full_name": "New Name"
"/groups/group2/members/user1/full_name": "New Name"

The above code assumes the user is in group1 and group2, but he could possibly in other groups too, how are you suppose to get a list of groups because you never know which group he is in without checking each one, so it ends up in a foreach loop again checking the user groups first? And thanks again Frank, Yes i assumed doing a foreach loop would be a very time consuming process, I guess that's not the case with firebase. I will experiment with this.

UPDATE 2

So i am testing this using angularfire2, here is my original code:

tours: any[];

this.firebase.get_user_tours().snapshotChanges()
.takeUntil(this.ngUnsubscribe).subscribe(tours => {
  this.tours = tours
}

and now i am using this because i am changing my database structure.

tours = [];

this.firebase.get_user_tours().snapshotChanges()
.takeUntil(this.ngUnsubscribe).subscribe(tours => {
  tours.forEach(tour => {
    this.firebase.get_tour(tour.key).snapshotChanges()
    .takeUntil(this.ngUnsubscribe).subscribe(tour => {
      this.tours.push(tour)
    })
  })
}

both works, but with pushing an object into an array, everytime i make an update to a tour, it adds a new object into the array instead of updating the original one, which makes sense, but is this what i'm suppose to do?

Mindless
  • 2,352
  • 3
  • 27
  • 51

1 Answers1

0

do i have to get a list of ids first and then do a foreach to get each individual user info and then add them to an array?

Yes, this sort of client side join is normal with Firebase. It's also not as slow as most developers think, because Firebase pipelines the requests.

if i update user1 full_name, how do i update it inside different groups too?

In this data structure you've duplicated the full name in multiple places. I cover the most common ways to keep this duplicated data up to date here: How to write denormalized data in Firebase

In your code a simple multi-location update would write these locations:

"/users/user1/full_name": "New Name",
"/groups/group1/members/user1/full_name": "New Name"
"/groups/group2/members/user1/full_name": "New Name"

This is indeed more work then if you'd just have to update the name in a single place. But in return for that, reading a group's member is now a lot simpler.

Whether it is better to duplicate data like this, or to perform the client side join depends in your app's requirements and your comfort level with duplicating data.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thank you, i have a question based on your answer, I will edit it in my original question – Mindless Dec 14 '17 at 23:40
  • Yes, you will need to know the groups of the user in order to update them. This might involve a query, or a direct read (if you keep a separate list of "groups for each user"). – Frank van Puffelen Dec 15 '17 at 01:28