0

I'm still pretty new to Firebase and still learning how to do "simple" things with it. I have a structure that looks like this:

"users": {
   "-KY5FJBudXmKv07noYbZ": {
        "emailAddress" : "a@a.com",
        "tags": {
             "red": "8dfhj34sd983ie",
             "green": "9f5d6g8er2d"
        }
    },
   "-KY5JM-NGjNgUXwrBRhs": {
        "emailAddress": "b@b.com",
        "tags": {
             "blue": "58ewgsg656fd",
             "pink": "sdf6g3dg5e6d"
        }
    },
   "-K_0c7wslBiOceF30R-5": {
        "emailAddress": "c@c.com",
        "tags": {
             "blue": "58ewgsg656fd",
             "brown": "xx4f5g68d5d1",
             "black": "8941gs8536sdf1"
        }
    },
}

What I want to do is fetch the nodes within users that contain a child in its tags where that value is 58ewgsg656fd.

In this example, that would be the "blue": "58ewgsg656fd" child and the users nodes that contain them are last two (...0R-5 and ...BRhs) one in that structure.

This is what I have so far:

DatabaseReference usersRef = database.getReference("users");
usersRef.orderByChild("tags").[NOT SURE WHAT GOES HERE].addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if (dataSnapshot.getChildrenCount() == 0) {
            // No users found with that tag
        } else {
            // Users found with that tag
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Error occurred
    }
});

What code should I write to fetch those nodes?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Brian
  • 7,955
  • 16
  • 66
  • 107
  • u should try to reverse the order of key-value pairs of tags . then it would be easier – Rishabh Maurya Dec 28 '16 at 19:53
  • So say I did do that, how would I go about querying by "key" instead of "value"? – Brian Dec 28 '16 at 20:01
  • 1
    Even if you invert the keys and values (or add an additional child node with the inverted key/values) this will still be a difficult query, since you'll need to define indexes for all values. In cases like this it is better to add a top-level lookup list mapping from values to paths. See my answer here: http://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value – Frank van Puffelen Dec 28 '16 at 20:05
  • Wow @FrankvanPuffelen, an engineer at Firebase! Thanks for that response, I'll think about how I can restructure this. Your chatroom example makes sense. – Brian Dec 28 '16 at 20:18
  • Quick unrelated question, when I use data persistence `database.getReference("users").keepSynced(true)`, does that actually mean my Android client "downloads" the entire contents of the `users` node? – Brian Dec 28 '16 at 20:21
  • When you tell the client to keep a node synchronized between your client and the database, it will download all data under that node and any changes to that data. – Frank van Puffelen Dec 28 '16 at 20:53
  • Is that considered "unsafe" because if I deploy this to the public, wouldn't that be downloading the entire `users` node to anyone's device and potentially letting someone look at all the data if they somehow could access the cached data stored on disk? – Brian Dec 28 '16 at 20:59
  • See also [NoSQL data modeling techniques](https://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/) – Kato Dec 28 '16 at 21:41

1 Answers1

1
ArrayList<String> user=new ArrayList<>();
DatabaseReference usersRef=FirebaseDatabse.getInstance().getReference();
usersRef.child("users").addValueEventListener(new ValueEventListener()
{
 public void onDataChange(DataSnapshot dataSnapshot) {
           Iterator<DataSnapshot>iterator=dataSnapshot.getChildren().iterator();
while(iterator.hasNext())
{
 DataSnapshot snapshot=iterator.next();
 if(snapshot.child("tags").child("58ewgsg656fd").exists())
 {
 user.add(snapshot.getKey());
 }
}

 }

 @Override
 public void onCancelled(DatabaseError databaseError) {

        }
});
Rishabh Maurya
  • 1,448
  • 3
  • 22
  • 40
  • 1
    This works, but it doesn't seem scalable. If I had thousands of users, wouldn't this involve iterating over all the users and potentially causing the app client to "download" through all the user data just to iterate through this in the worst case? – Brian Dec 28 '16 at 20:20
  • Yeah , it is not scalable for large number of users but till now I have been able to figure out getting only desired response data . – Rishabh Maurya Dec 28 '16 at 20:23
  • 1
    It's as scalable as any other method for downloading a large number of users. The primary limitation here is the internet--i.e. bandwidth--and the number of bytes being downloaded. To improve throughput, download less data. – Kato Dec 28 '16 at 21:42