0

I am using Firebase Realtime database in my Android app. How can I query field Ingridients in my database and get all meanings in ArrayList?

There is structure of my database:

{
  "Receptes" : [ {
    "Ingridients" : [ "Carrot", "Salt", "Apples" ],
    "Name" : "Food"
  } ]
}

enter image description here

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Felay
  • 221
  • 3
  • 8
  • what do you mean `get all meanings`? –  May 13 '18 at 19:19
  • I mean that I need get `Carrot`,`Salt` and `Apples` into my `ArrayList` – Felay May 13 '18 at 19:22
  • 1
    Could you edit the question to show the code that you've tried that's not working the way you expect? – Doug Stevenson May 13 '18 at 19:31
  • At first glance it looks like you're trying to use an array for storing a set of data. See [my answer here](https://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value) for why it's not possible to query recipes based on their ingredients with this structure, and how to instead structure your database to allow the query. – Frank van Puffelen May 13 '18 at 22:41
  • Possible duplicate of [Firebase query if child of child contains a value](https://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value) –  May 14 '18 at 12:18

2 Answers2

0
DatabaseReference recept = FirebaseDatabase.getInstance().getReference("Receptes");
DatabaseReference vegies = recept.child("Ingridients");

Check the documentation for more explanation.

You also need to add a listener

recept.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Log.i(TAG, dataSnapshot.child("Ingredients").getValue(String.class);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w(TAG, "onCancelled", databaseError.toException());
    }
});
0

Although Firebase Realtime database can store arrays, it does not support querying array members or updating single array elements. So to solve this, I recommend you an alternative database structure that looks like this:

{
  "Receptes" : {
    "Ingridients" : {
      "Carrot" : true,
      "Salt" : true,
      "Apples" : true
    },
    "Name" : "Food"
  }
}

As you can see, now the Receptes and the Ingridients are stored as a Maps and not as an arrays. And to query your database to display all ingridients, please use the following code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ingridientsRef = rootRef.child("Receptes").child("Ingridients");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String ingridient = ds.getKey();
            Log.d("TAG", ingridient);
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
ingridientsRef.addListenerForSingleValueEvent(valueEventListener);

According to your comment, the database should look like this:

{
  "Receptes" : {
    "Ingridients" : {
      "IngridientIdOne" : {
        "Carrot" : true,
        "Salt" : true,
        "Apples" : true
      },
      "IngridientIdTwo" : {
        "Strawberries" : true,
        "Sugar" : true,
        "Bananas" : true
      },
    },
    "Name" : "Food"
  }
}
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • But how will the structure of the database look like with a lot of recipes? And how can I get the `Name` of each unique recept? – Felay May 14 '18 at 09:47
  • You can achieve this by adding an ingredient id under the `Ingridients` node, as in my updated answer. See, IngridientIdOne, IngridientIdTwo? – Alex Mamo May 14 '18 at 10:00
  • Okay. How can I get values `IngridientIdOne` and `IngridientIdTwo` in this `ValueEventListener`? – Felay May 14 '18 at 11:02
  • As you can see in my code, to query your database, those ids are not needed. But if you want to have them, just store those ids in a variable when adding the ingridients, right? – Alex Mamo May 14 '18 at 12:16
  • why when I using your code line `String ingridient = ds.getKey();` is not return ingridients but return `IngridientIdOne`? – Felay May 16 '18 at 11:33
  • Because `ds.getKey()` returns the key and the value. That's why. – Alex Mamo May 17 '18 at 10:31