2

I'm building a chat app with Firebase (and AngularJS) and I have a data structure that is similar to the one on this Firebase documentation page. This structure is good for not having to retrieve huge amounts of unneeded data but I don't seem to understand a very simple thing.

With my data looking like below, when a user connects to my app:

How do I retrieve their 10 most recently updated groups and keep this list updated as new messages are posted in groups?

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      },
      "lastUpdateTime": [SOME TIMESTAMP HERE]
    },
    ...
  }
}

More information if you care to read


As you can see, I've added "lastUpdateTime": [SOME TIMESTAMP HERE] to the code above because it's how I do it for my app. I can't figure out what should be the "refresh process" for a user group list.

If my user has 100 groups, should I retrieve a list of the group IDs and get the actual groups one by one to be able to only keep the 10 most recent (I'm pretty sure this is not the way to go)?

Also, whenever someone posts a message in a group, it will update the lastUpdateTime in Firebase but how do I keep the user group list synchronized to this?

I've tried some very ugly combinations of child events, orderBys as well as entire chains of functions executing whenever something fires but it doesn't work and seems extremely complicated, for nothing. The whole idea of flattening the data is to keep the queries/fetching to a minimum and I feel that what I have done so far is way too heavy.

Community
  • 1
  • 1
Gonzo
  • 47
  • 7

1 Answers1

2

To show the list of the 10 most recently updated groups:

ref.child("groups").orderByChild("lastUpdateTime").limitToLast(10)

If you use this approach, please flatten your data further, since the query will now end up retrieving the members of each group, which is not needed for displaying a list of groups.

If you want to a list of the groups the user is subscribed to by order of the last update, you have a few options:

  • store the last update timestamp for each user's subscriptions
  • load the user's groups and re-order them client-side

store the last update timestamp for each user's subscriptions

Store the timestamp the group was last updated for each user subscribed to the group:

"usersgroups": { "alovelace": { // the value is the timestamp the group was last updated "techpioneers": 14952982198532978, "womentechmakers": 14852982198532979 },

You'll note that I split the group memberships from the user profiles here, since you shouldn't nest such loosely related data.

Then you can get the list of the user's group in the correct order with:

ref.child("usersgroups/alovelace").orderByValue()

The main problem with this approach is that you'll need to update the timestamp of a group for all members for ever post. So writes become a lot more expensive.

load the user's groups and re-order them client-side

This may sound like it'll be slower, but it actually won't be too bad. Since you're only loading the groups the user is a member of, the number won't be too high. And Firebase pipelines the requests, so performance is a lot better than you may expect. See Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 1
    Thank you very much for this, it's exactly the kind of answer I needed. I'm tempted to go for the first option since my groups will have a limited amount of users. Could you tell me a bit more about "writes become a lot more expensive"? Is it going to make the app "sluggish" or are we talking about a delay in getting updates client-side? Would you recommend the first approach if I have a limited amount of users per group? I'd like to understand why and how bad it could get. Is it because Firebase would have tons of requests to process? – Gonzo Jan 17 '17 at 21:43
  • I am personally more likely to just load the user's groups and re-order them client-side. The best advice is to try both approaches and see what works best/feels most natural to you. – Frank van Puffelen Jan 17 '17 at 22:58