Retrieve complex nested data from firebase - android

I have the data in firebase as given below:
I want to get the Customer and Device details for each of the Form ID. The Form IDs are generated uniquely by firebase.
I just somehow need to get access to these Form IDs.
I have set the databaseReference as follows:
databaseReference = FirebaseDatabase.getInstance().getReference("users").child(userID).child("forms");
Then I have tried the following code to retrieve the required data:
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot formsSnapshot : dataSnapshot.getChildren()) {
for (DataSnapshot formIDSnapshot : formsSnapshot.getChildren()) {
Device device = formIDSnapshot.getValue(Device.class);
if (device != null) {
// get and use the data
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Update:
I am now successfully able to retrieve the form IDs, thanks to the answer by #Frank.
Now, to get the Device and Customer details I have to write the following code inside the ValueEventListener after getting the form IDs:
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot formsSnapshot : dataSnapshot.getChildren()) {
String formID = formsSnapshot.getKey(); //Retrieving the formID here
//New code addition
// to get the reference to device details node
databaseReference.child(Objects.requireNonNull(formID)).child("Device details").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Device device = dataSnapshot.getValue(Device.class);
if (device != null) {
// required device details here
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
// to get the reference to customer details node
databaseReference.child(Objects.requireNonNull(formID)).child("Customer details").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Customer customer = dataSnapshot.getValue(Customer.class);
if (customer != null) {
//required customer details here
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
I understand that this is a messy code and I would like to get some cleaner approach for the same.

You can get the key of a node by calling DataSnapshot.getKey(). So to get your form IDs:
databaseReference = FirebaseDatabase.getInstance().getReference("users").child(userID).child("forms");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot formsSnapshot : dataSnapshot.getChildren()) {
String formID = formsSnapshot.getKey();
Device device = formsSnapshot.getValue(Device.class);
if (device != null) {
// get and use the data
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});

There is no need for the nested loops. Simply get the children list and loop over it once. At every iteration, cast dataSnapshot to FormID class and afterwards just use its properties.
i would also suggest that you use SingleValueEventListener instead of ValueEventListener if you do not need to observe the data all the time

Related

How can I fetch certain type of data from Firebase Realtime Database?

I know that there is a lot of code on this, but I can't find the solution for my problem.
I have a realtime database :
I have to fetch "saluteBossMassima:"
The way I have declared and initialized my variables:
DatabaseReference databaseMonster;
String id;
databaseMonster=FirebaseDatabase.getInstance().getReference("monster");
id = databaseMonster.push().getKey();
The code that I try:
databaseMonster.child(id).addValueEventListener(newValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String saluteMassimaBossDB = dataSnapshot.child("monster").child("saluteBossMassima").getValue().toString();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Anyone can help me?
This won't work:
databaseMonster=FirebaseDatabase.getInstance().getReference("monster");
id = databaseMonster.push().getKey();
When you call push() it generates a new unique key for writing to. There is zero chance that this is the same as the existing key in your screenshot.
If you already know the key of the node you want to read, you should pass that key to child():
// 👇 specify key here
databaseMonster.child("-MtcylP327pK9pUQB54").addValueEventListener(newValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String saluteMassimaBossDB = dataSnapshot.child("saluteBossMassima").getValue(String.class);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException(); // 👈 never ignore errors
}
});
If you know some value of the node(s) you want to read, but not the key, you can use a query to find the nodes:
// 👇 Use a query to select the nodes with a specific value
Query query = databaseMonster.orderByChild("dannoAttaccoCaricato").equalTo(300);
query.addValueEventListener(newValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// 👇 Loop over the results, since there may be multiple
for (DataSnapshot monsterSnapshot: dataSnapshot.getChildren()) {
String id = monsterSnapshot.getKey();
String saluteMassimaBossDB = monsterSnapshot.child("saluteBossMassima").getValue(String.class);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});
Now we need to loop over dataSnapshot.getChildren(), since there may be multiple nodes with the value of 300 for dannoAttaccoCaricato.
If you know nothing about the node, the best you can do is read all of them and loop over the results:
// 👇 Read all nodes under /monster
databaseMonster.addValueEventListener(newValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot monsterSnapshot: dataSnapshot.getChildren()) {
String id = monsterSnapshot.getKey();
String saluteMassimaBossDB = monsterSnapshot.child("saluteBossMassima").getValue(String.class);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException();
}
});

Android Firebase push and get Array List

I have a questions how could i push array list to my freebase data base
and also read it to add a new element , then push it again.
In the above photo you can see i have added array list joinedStudents
and i need to read it and push new elements to it
I've tried the following
DatabaseReference requestsRef = FirebaseDatabase.getInstance().getReference();
requestsRef.child("requests").child(requestID).child("joinedStudents");
requestsRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot d : dataSnapshot.getChildren()) {
String jR = d.getValue(String.class);
joinedStudents.add(jR);
}
joinedStudents.add(studentID);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, "error fetching data from firebase");
}
});
for (String string : joinedStudents) {
requestsRef.child("requests").child(requestID).child("joinedStudents").setValue(string);
}
but it's not working
I believe you have your references slightly mixed up. Try something like:
DatabaseReference joinedStudentsRef = FirebaseDatabase.getInstance().getReference().child("requests").child(requestID).child("joinedStudents");
joinedStudentsRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot d : dataSnapshot.getChildren()) {
String jR = d.getValue(String.class);
joinedStudents.add(jR);
}
joinedStudents.add(studentID);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, "error fetching data from firebase");
}
});
for (String string : joinedStudents) {
joinedStudentsRef.child("1").setValue(string); // setValue is for key, value
// but you have an array
}
Where your reference is now the direct node that you want to monitor/read/write

How to get key of elements in firebase?

I am an absolute beginner in Android and Firebase. Forgive me for my post. I want to get the key element that is under "node" eventos. Till I have done the following code, but I am no able to get the key. Please help me, I am doing my college project.
DatabaseReference mDataBase = `FirebaseDatabase.getInstance().getReference();`
DatabaseReference usuarios = mDataBase.child("usuarios");
DatabaseReference eventos = usuarios.child("eventos");
eventos.orderByValue().equalTo("eventos").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snap : dataSnapshot.getChildren()){
String key = snap.getKey();
System.out.println("LAS CLAVES SON: "+key);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
enter code here
}
});
I want to get the key to update each element and delete.
you have to just remove your some code :-
eventos.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snap : dataSnapshot.getChildren()){
String key = snap.getKey();
System.out.println("LAS CLAVES SON: "+key);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
enter code here
}
});

Firebase query 2 same methods one is working,other not

I got 2 same methods in one I declare string in Query and on another I declare it thru variable, but when I run apk the one I declare string inside Query works but the other does not.
First method:
private void randomtest() {
Query query = FirebaseDatabase.getInstance().getReference("users").orderByChild("username").equalTo("darkarcher5");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot users : dataSnapshot.getChildren()) {
User user = users.getValue(User.class);
Log.e("username", user.getUsername());
Log.e("password", user.getPassword());
userList.add(user);
}
txtViewPass.setText(userList.get(0).getUsername());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
Second method:
private void neRandomTest() {
if (username != null) {
Query query = FirebaseDatabase.getInstance().getReference("user").orderByChild("username").equalTo(username);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot users : dataSnapshot.getChildren()) {
User user = users.getValue(User.class);
Log.e("username", user.getUsername());
Log.e("password", user.getPassword());
userList.add(user);
}
txtViewPass.setText(userList.get(0).getUsername());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Error given by second method: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
In your first method, your query is referencing on the "users" node while on your second method your query is referencing on the "user" node. If I am correct you are trying to connect to "user" node in second method which is not available in the firebase database. That's why indexoutofbounds.
Try using this:
private void neRandomTest() {
if (username != null) {
//Query query = FirebaseDatabase.getInstance().getReference("user").orderByChild("username").equalTo(username);
Query query = FirebaseDatabase.getInstance().getReference("users").orderByChild("username").equalTo(username);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot users : dataSnapshot.getChildren()) {
User user = users.getValue(User.class);
Log.e("username", user.getUsername());
Log.e("password", user.getPassword());
userList.add(user);
}
txtViewPass.setText(userList.get(0).getUsername());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}

Android Firebase Retrieve Realtime Data

I try to get data from the database.
Code:
mDatabaseUsers = FirebaseDatabase.getInstance().getReference().child("User")mDatabaseUsers.orderByChild("name").startAt("m");
mDatabaseUsers.keepSynced(true); mDatabaseUsers.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<String, String> map = dataSnapshot.getValue(Map.class);
String name = map.get("name");
Toast.makeText(AddFriendActivity.this,nick.toString(),Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I want to get all users with the letter m!
How does is work?
Thank you!
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So you'll need to loop over the results in dataSnapshot:
mDatabaseUsers.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
System.out.println(userSnapshot.child("name").getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
Also see the brief example in the Firebase documentation on using a value event to get a list of results.

Categories

Resources