I am trying to retrieve a nested list of workouts from a Realtime Database and I don't know how to do it.
I made some research and still couldn't really figure out how am supposed to do it.
The Realtime Database JSON file looks like this :
I am looking to retrieve data by workout, for example, if someone presses the workout one button I should retrieve the full workout one object. but I don't know how am supposed to design my query request nor how am supposed to structure my model object that conceives the received data.
As I see in your screenshot, under the "Workout one" node, you have two nested levels of data. So to get all exercises for each day, you have to loop over the children twice:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference workoutOneRef = db.child("Fat Loss").child("Workout one");
workoutOneRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot daySnapshot : task.getResult().getChildren()) {
for (DataSnapshot exerciseSnapshot : daySnapshot.getChildren()) {
String name = exerciseSnapshot.child("name").getValue(String.class);
Log.d("TAG", name);
}
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
Please also don't forget that the Firebase API is asynchronous. So any code that needs data from the database needs to be inside the onComplete() method, or be called from there. To understand better, I recommend you check the following resource:
How to read data from Firebase Realtime Database using get()?
I think below line code help you.
databaseReference = FirebaseDatabase.getInstance().getReference().child("Fat Loss").child("Workout one").child("day 1")
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
allTaskList.clear();
if (snapshot.exists()) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
//modal class object
AddTODOListModal model = dataSnapshot.getValue(AddTODOListModal.class);
assert model != null;
model.setId(dataSnapshot.getKey());
allTaskList.add(model);
}
adapter = new TODOListAdapter(TODOListHomeActivity.this, allTaskList);
binding.rvTODO.setAdapter(adapter);
}else {
Utils.showToast("No Data Available");
}
Utils.dismissProgressDialog();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Utils.showToast(error.getDetails());
}
});
Reference link :- https://firebase.google.com/docs/database/android/lists-of-data
Related
I want to get a User or just a User UID via email or name. Tried to write the query, but I'm getting all users and then iterating through them and then getting the user but I think it's an expensive task. How can I get only one User/Uid from Realtime Database?
This is what I came up with (But don't think is the best way):
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("Users");
Query emailQuery = usersRef.orderByChild("email").equalTo(client.getEmail());
emailQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot child : snapshot.getChildren()) {
if (child.getValue(User.class).getEmail().equals(client.getEmail())){
User user = child.getValue(User.class);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
According to your last comment:
I have the corresponding details of each user (email, name), and I want to get the UID of one user (no matter which one)
To get a particular user from the database based on a particular email address, the query that you are already using:
Query emailQuery = usersRef.orderByChild("email").equalTo(client.getEmail());
Returns only the users who have the field email set to what client.getEmail() returns. For instance, if client.getEmail() returns tedo#gmail.com then you'll get a single result, according to your screenshot, which is the first one. That being said, the following if statement, doesn't make sense to be used:
if (child.getValue(User.class).getEmail().equals(client.getEmail())){
User user = child.getValue(User.class);
}
Since the key of the user node is represented by the UID, then you should get it like this:
Query emailQuery = usersRef.orderByChild("email").equalTo(client.getEmail());
emailQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot child : snapshot.getChildren()) {
User user = child.getValue(User.class);
String uid = child.getKey();
//Do what you need to do with UID.
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.d("TAG", error.getMessage()); //Never ignore potential errors!
}
});
That's the simplest, cheapest way to query the Realtime Database, in which you return only the elements that you are interested in and that satisfy a particular condition.
how can I extract all the "name" values contained in DATA?
I tried this to extract a single name but it doesn't work:
DatabaseReference myRef = FirebaseDatabase.getInstance().getReference("ALL");
Query query = myRef.orderByChild("name").equalTo("pluto");
Two problems:
The code you shared only declares a query. It doesn't read anything from Firebase yet.
You're trying to order/filter in a child property, but are not specifying the full path to that property.
The second one is easiest to fix:
DatabaseReference myRef = FirebaseDatabase.getInstance().getReference("ALL");
Query query = myRef.orderByChild("DATA/name").equalTo("pluto");
And then you can read the results with:
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
Log.i("Firebase", snapshot.getKey());
Log.i("Firebase", snapshot.child("name").getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
Thanks
I edited it so the log is working
Log.i("Firebase", snapshot.child("DATA/name").getValue(String.class));
If I want to print all the names, how should I do it?
I do password recovery and I need to know if there is a user in the database with the entered E-mail'om. How do I do that? Here is the structure:
For example, the user entered E-mail - goshan164#gmail.com and I need to know if there is such a mail in my database. And if it exists, then find out the uID of the user with such mail. How do I do that?
P.S uId initially I do not know. In the picture uId = zKCTYc1JkROrGxgOZgvm9CvfSU42
You're looking for a Firebase database query, in this case one that compares the child property of each node against the value you're looking for:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users"); // or whatever your node is
Query query = ref.orderByChild("account").equalTo("goshan164#gmail.com");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
System.out.println(userSnapshot.getKey());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
For more on this, see the Firebase documentation on ordering an filtering data.
This is the Firebase database structure of my project.
I want to fetch complaint division, describe, stat for the particular hostelname and roomno. How to fetch these data and display in android project?
To get all those values, please use the following lines of code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference complaintsRef = rootRef.child("Complaints");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String complaintDivision = ds.child("complaintdivision").getValue(String.class);
//Get the other properties in the same way
Log.d(TAG, complaintDivision);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
complaintsRef.addListenerForSingleValueEvent(valueEventListener);
The output in your logcat will be:
Plumber Related
This is a basic function in Firebase on Android. You can use ValueEventListeners with the database reference to do this.
The steps to achieve the desired results can be enlisted as below:
Create a Complaint model with the same fields as your database.
Get the right Firebase reference for your database node and add a ValueEventListener instance to listen for database changes.
Pass a DataSnapshot into the Complaint class and assign it to a Complaint object.
Do what you want with the Complaint object you have obtained.
Creating a Complaint class:
class Complaint {
// your fields should have the same name as database fields to prevent unnecessary complications
public String complaintdivision;
public String complaintid;
public String describe;
public String hostelname;
public String roomno;
public String stat;
public Complaint(){// required for Firebase
}
}
Getting the data from Firebase:
ArrayList<Complaint> myComplaintArrayList = new ArrayList<>();
FirebaseDatabase.getInstance().getReference().child("Complaints").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot complaint: dataSnapshot.getChildren()){
Complaint c = complaint.getValue(Complaint.class);
myComplaintArrayList.add(c);// you should have an ArrayList<Complaint> for this loop
}
// do what you want with the items you obtained
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
This is pretty much all of it. If you are still having problems, you should read a tutorial on Firebase.
So to fetch the data you would first declare a Firebase DatabaseReference object that points to your database:
private DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
You would then write a query using this object:
Query query = mDatabase.child("Complaints");
Now you attach a SingleValueEventListener to this query:
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Write a for-each loop to cycle through your node's children
for(DataSnapshot data: dataSnapshot.getChildren()){
//Create an instance of your model class to
//store the received data
//Make sure you have an empty constructor in your model class
Complaint complaint = data.getValue(Complaint.class);
//then simply call your getters on the complaint object
//to get what you need
complaint.getComplaintDivision();
complaint.getDescription();
//...
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
To fetch more specifically, you just modify the query.
For more information on queries, see this
I have the following database structure in Firebase:
I would like to retrieve all objects from "chats" if in the "users" object contains the key "user2".
Is it possible to download the data as written with no change of structure Firebase?
My actually code to get data:
DatabaseReference chatReference = FirebaseDatabase.getInstance().getReference("conversationsNew");
chatReference.orderByChild("users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("TAG", dataSnapshot.getChildrenCount());
for (DataSnapshot chat : dataSnapshot.getChildren()) {
Log.d("TAG", chat.toString());
Chat chat = chat.getValue(Chat.class);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Thank you very much.
That's quite possible:
DatabaseReference chatReference = FirebaseDatabase.getInstance().getReference("chats");
chatReference.orderByChild("users/user1").equalTo(true).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot chat: dataSnapshot.getChildren()) {
Log.d("TAG", chat.getKey());
Chat chat = chat.getValue(Chat.class);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
This will print:
chat1
But this approach will not scale, since you'll need to add an index for each user. To prevent this, you'll need a data structure that more closely reflects the use-case. So: if you want to show a list of the chats that the current user is in, you'll need to store precisely that: a list of the chats for each user. Alex' answer shows the most common way of storing such data.
No, there is no possibility for achieving this using your code. What can you do instead, is to change a little bit your database structure, by adding a new node like this:
Firebase-root
--- users
--- userId1
--- userName: John
--- chats
--- chat1: true
Having this, you can query your database for getting the chats in which your user belong. To verify for existens you only need to use exists() method on the dataSnapshot object.
Hope it helps.