Search code examples
javaandroidfirebasefirebase-realtime-databasefirebaseui

Get index data with setIndexedQuery where index not end of path


I have a Firebase realtime database with a layout similare to this:

{
  "data": {
    "index_1": {
      "xxx": {
        "value_1": "Some data",
        "value_2": true
      },
    "index_2": {
      "xxx": {
        "value_1": "Some data",
        "value_2": true
      },
    "index_3": {
      "xxx": {
        "value_1": "Some data",
        "value_2": true
      },
   },
   "keys": {
     "user1": {
       "index_1": true,
       "index_2": true
     },
     "user2": {
       "index_1": true,
       "index_3": true
     }

   }
}

And a simple java class:

public class Data {
    private String value_1;
    private Boolean value_2;
    ...
    getters/setters
    ...
}

Is there any (easy) way to get objects from /data/{index}/xxx/{object}?

If the layout had been /data/{index}/{object}, eg:

"data": {
  "index_1": {
    "value_1": "Some data",
    "value_2": true
  }
}

it's is possible to use

keyQuery = FirebaseDatabase.getInstance()
                           .getReference("keys")
                           .orderByKey();
dataRef = FirebaseDatabase.getInstance().getReference("data");
FirebaseRecyclerOption<Data> options = new FirebaseRecyclerOptions.Builder<Data>().
        .setIndexedQuery(keyQuery, dataRef, Data.class)
        .build();

but I havn't found any way to do this when the index isn't just before the wanted data.


Solution

  • Is there any (easy) way to get objects from /data/{index}/xxx/{object}?

    Yes it is, using the following lines of code:

    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference dataRef = rootRef.child("data");
    ValueEventListener valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot ds : dataSnapshot.getChildren()) {
                String value_1 = ds.child("xxx").child("value_1").getValue(String.class);
                boolean value_2 = ds.child("xxx").child("value_2").getValue(Boolean.class);
                Log.d(TAG, value_1 + " / " + value_2);
            }
        }
    
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
        }
    };
    dataRef.addListenerForSingleValueEvent(valueEventListener);
    

    If you want to use FirebaseRecyclerOption, you database schema should indeed looks like this:

    "data": {
      "index_1": {
        "value_1": "Some data",
        "value_2": true
      }
    }
    

    Without that extra xxx child.