6

My data is denormalized and uses a reverse index like suggested by the firebase team. Something similar to:

{
  "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
      }
    },
    ...
  }
}

Now I want to load all of Ada's groups. I can easily get a list of the group IDs that she belongs to since it's part of her user object.

Is there a way for me to query all of Ada's specific groups by ID at once? Or do I need to create a ValueEventListener per group ID and request each group separately?

On the security side - let's assume that every group is only readable by its members, so I can't query all groups and sort them after the fact.

Itai Hanski
  • 8,540
  • 5
  • 45
  • 65
  • Most applications through the keys from the index and load each group individually. That's not a big performance drain, since Firebase pipelines the database requests. See http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786 – Frank van Puffelen Jul 13 '16 at 16:53
  • @FrankvanPuffelen Do you mean that if I loop through the list and set a `ValueEventListener` for each of them, the DB will optimize the way it retrieves the data on its own? Or do I have to request the data in a certain way? – Itai Hanski Jul 17 '16 at 12:31
  • All requests go through the same connection. The only difference between `get(1)`, `get(2)`, `get(3)` and `getAll([1,2,3])` is some overhead for the frames. – Frank van Puffelen Jul 19 '16 at 23:28
  • @ItaiHanski also struggling with the same issue - did you find a better solution? All answers I've found seen like a "hack". – eth0 Jul 05 '17 at 09:40
  • @eth0 Not really. I basically create a listener per group and wait until all of them return an answer to logically be "loaded" – Itai Hanski Jul 05 '17 at 14:20

1 Answers1

1

I guess you could do something like:

var ref = new Firebase("<..>/groups");
ref.orderByChild("members/alovelace").equalTo(true)
  .once('value').then(function(dataSnapshot) {
     // handle read data
})

(Untested, but according to this Deep-Queries are now supported)

Timo
  • 1,724
  • 14
  • 36
  • in Android use this: Query query = mFirebaseDatabaseReference.child("groups").orderByChild("members/" + user.getId()).equalTo(true); . this is one query for all data! – itzhar Dec 29 '16 at 12:17
  • This approach has 2 drawbacks IMO: First, from a security standpoint - this means that every user can read the entire `groups` tree, and second, If I have a huge number of groups this would probably be a little slow and wasteful. I already know the exact IDs of the groups I'm interested in - seems a shame not to use it. – Itai Hanski Jan 15 '17 at 13:07
  • @ItaiHanski did you figure out the solution? – Muhammad Umar Oct 02 '18 at 06:54
  • @MuhammadUmar Nothing fancy. Iterate through all of the fetches and make sure they all return. – Itai Hanski Oct 22 '18 at 07:53