BomberBus
BomberBus

Reputation: 1235

Android Firebase Query with Multiple Keys

This kind of question is already asked and some already had answered. But I have some confusion and that why I post that question. After I read the Firebase doc about "how to structure data in firebase from here", I googled and tried to query the group list of a user (for a couple of days and still haven't got the solution).

enter image description here

Assume we already have the group ids that the user participated from the /users/{$user_id} node and we would like to get the group details list from /groups note by the groupd id list. For example, something like the below query.

SELECT * FROM groups WHERE key = "techpioneers" AND key = "womentechmakers";

According to google search result and stackoverflow answers, Firebase doesn't support multiple where clause. Iterating /groups/{$groud_id} node one by one to get the group detail list is also not a good approach.

Sorry for long question. Please help how to query such kind of data list with multiple keys form Firebase using Firebase android SDK.

Upvotes: 3

Views: 4679

Answers (1)

martinomburajr
martinomburajr

Reputation: 1265

One of the downsides of the Firebase Realtime Database is its inflexibility with data structuring. If you want to perform queries that look at different data nodes you almost always need to denormalize your data. This has the benefit of

  1. Decomposing your data into discreet chunks
  2. Better querying for stats etc
  3. You don't have to download massive chunks of nested data

The downside is that:

  1. Your data requires multiple combined queries e.g user-by-username' or groups-by-user`.
  2. It seems a bit convoluted and non-intuitive

Back to your question: Given the following table structure:

group
    group1
        name:"Best group"
        description: "The best group"
    group2:
        name:"An okay group"
        description: "A decent group"
user
    user1
         name: "User1"

    user2
         name: "User2"
group-by-user
    user1
         group1: true
         group2: true
    user2
         group2: true

Note how I have created a new table that will associate a user to a group without having to place this info in the user table. This ensures that the user table is solely for base non-relational user information.

To query this in Java, it would look something like the following

//Get a reference to groups a user is in
       //get a reference
    DatabaseReference groupByUserRef = FirebaseDatabase.getInstance().getReference();
    //get a reference to the join table mentioned above
    groupByUserRef.child("group-by-user").child("user1").addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            //This contains a list of group keys associated to the user;
            Iterable<DataSnapshot> groupsByUser = dataSnapshot.getChildren();
            //iterate through the list of group keys associated to the user
            groupsByUser.forEach(groupDatasnapshot -> {
                String groupId = groupDatasnapshot.getKey();
                FirebaseDatabase groupReference;
                DatabaseReference groupRef = FirebaseDatabase.getInstance().getReference();

                //Once the key has been retrieved, do a search in the database to get the group
                groupRef.child("group").child(groupId).addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        //Here is where you will get the groups associated to the user.
                        Group group = dataSnapshot.getValue(Group.class);
                        //Add logic here ..
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
            });
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

EDIT To conclude As mentioned above you can see it is a very convoluted approach. This is a drawback of the Realtime database. If you would like to ensure not looping over keys you have the following option.

  1. Don't denormalize your data and have the group information directly within the user table. This has the downside of you having to pull large sets of data when your group info grows (some of which you wont need).
  2. Use firebase cloud firestore - they have managed to solve the problem here

Upvotes: 3

Related Questions