Google firebase check if child exists - java

In my app, I need to check if a given element of my database on firebase has a child with a given name. I hoped it could be done by using something along the lines of:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
if (rootRef.childExists("name")) {
//run some code
}
I searched but I couldn't find anything useful.

Edit 2; worth putting on top: I think it is worth mentioning that this is actually downloading all data at this snapshot just to check whether any data exists. You should be mindful here. If the reference is huge (e.g. actually the root reference and not a specific child/property) then you should either find a deeper node you can use to check for existence or design your data structure differently so an efficient check is possible.
A database reference is effectively the URL for that data. You want to actually get data to see whether a child exists. This is why the method you seem to be looking for is on DataSnapshot.
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
void onDataChange(DataSnapshot snapshot) {
if (snapshot.hasChild("name")) {
// run some code
}
}
});
Now, this design pattern feels a bit strange. You're reading the whole database just to see whether "name" exists. You can make this a bit more efficient by listening to rootRef.child("name") and then just checking whether snapshot.exists().
If you're trying to do validation here, and not control flow, you should consider putting this code in your rules.json.
edit: I originally used the wrong function name (childExists instead of hasChild)

Don't do like this
NEVER
It will take all your data and bring to device
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
void onDataChange(DataSnapshot snapshot) {
if (snapshot.hasChild("name")) {
// run some code
}
}
});
Check it by this way.
It will return the value of the child if exists, otherwise -> null
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
rootRef.child("childName")
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
void onDataChange(DataSnapshot snapshot) {
if (snapshot.getValue() == null) {
// The child doesn't exist
}
}
});

A complete solution. No need to download all the data. Just check if the child exist like this:
// Assuming the names are in the name node. Remove "name/" if not
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("name/" + name);
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.exists()) {
// Exist! Do whatever.
} else {
// Don't exist! Do something.
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed, how to handle?
}
});

Try using .childexists in combination with .equalTo("Your specific name")

UsersRef = FirebaseDatabase.getInstance().getReference();
Users.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if (snapshot.hasChild("childName")) {
// it exists!
}else{
// does not exist
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Use snapshot.exists() to check if the referenced database entry contains a child , irrespective of the value of the child.

Related

how do i retrieve a nested object from Firebase?

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

Firebase: child of child extract value

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?

How to get the random key paired with a specific value in firebase database and delete the value?

I have a simple database structure like so:
I need to remove the value earphone by using its key which is -M-4XBDqv-ve396r5EHm.
I have a button for deleting that value,
and I want to use this line of code to remove it:
mReferenceForListA.child("List A").child("Items").child(key).removeValue().
But how do I get the key for earphone?
I know I can just write
mReferenceForListA.child("List A").child("Items").child(-M-4XBDqv-ve396r5EHm).removeValue()
to delete earphone straight away,
but what if I need to delete other items in the list?
I'll need to pass a specific key into a variable called "key" to delete a specific value.
So, again, how could I get a specific key for the value that I want to delete in my current JSON structure?
This is what I tried:
Reading through related posts for days in stackoverflow and I came down to writing the following codes, but I don't think I got the hang of this thing yet and seriously need help. The following codes always delete the whole "List A" node, but in this case I just need to delete one specified value and keep the others intact in the node.
public static DatabaseReference mRootReference = FirebaseDatabase.getInstance().getReference();
public static DatabaseReference mReferenceForListA = mRootReference.child("List A");
deleteButton= findViewById(R.id.delete_button)
deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mReferenceForListA.child("Items").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postsnapshot :dataSnapshot.getChildren()) {
String key = postsnapshot.getKey();
mReferenceForListA.child("Items").child(key).removeValue();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
});
To delete a node you need to know its complete path. If you only know a value of (a property of) the node, you can run a query to find all nodes that match that value.
Something like:
public static DatabaseReference mRootReference = FirebaseDatabase.getInstance().getReference();
public static DatabaseReference mReferenceForListA = mRootReference.child("List A");
Query query = mReferenceForListA.child("Items").orderByValue().equalTo("earphone");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
snapshot.getRef().removeValue();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
The main changes:
The above uses a query on orderByValue() on the Items child. This means Firebase searches all child nodes directly under List A/Items and returns the ones whose value matches earphones.
It also uses addListenerForSingleValueEvent, so that the delete only runs once, instead of continuously.
It uses snapshot.getRef().removeValue() for a much shorter way to remove the node.
It implements onCancelled, since you should never ignore errors.
You should iterate through the DataSnapshot as you have done, but you also need to supply it with a condition to delete the entry with a specific value.
for (DataSnapshot postsnapshot : dataSnapshot.getChildren()) {
if(postsnapshot.child(postsnapshot.getKey()).getValue(String.class)).equals("earphone"){
mReferenceForListA.child("List A").child("Items").child(postsnapshot.getkey()).removeValue();
}
}
Let me know if this works as I am trying to write this from memory.

How to handle asynchronous Database with Firebase?

I have a lot of questions about handeling asynchronous database in my Android app.
Since I know that database is asynchronous, I've tried several things to handle it. As you can see in my code, I've two functions who need to use an array in my database. My first function (setArrayfromDatabase) will apply changes on my array in my database and my second function (setAnotherArray)need to use this array with changes applied from my first function. Here's my code :
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myReff =database.getReference("server").child("user");
myReff.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Take the array from my database
final ArrayList<Integer> array_from_database;
GenericTypeIndicator<ArrayList<Integer>> genericTypeIndicator = new GenericTypeIndicator<ArrayList<Integer>>() {};
array_from_database = dataSnapshot.getValue(genericTypeIndicator) ;
System.out.println("1");
//use this array in this first function, and this function will modify it.
setArray_for_database(array_from_database);
myReff.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//this will be executed only if my array is changed (So only if my other function have been correctly executed
setAnotherArray(array_from_database);
System.out.println("3");
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here's the code for setArray_for_database :
public void setArray_for_database(ArrayList<Integer> array_from_database){
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myReff =database.getReference();
//Take the array from my database (gived in parameter)
final ArrayList<Integer> array = array_from_database;
myReff.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//this will be executed, even if data hasn't been changed because of the method (addListenerForSingleValueEvent)
System.out.println("2");
array.set(0,3);
Map<String, Object> chemainChild = new HashMap<>();
chemainChild.put("server/user/",array);
myReff.updateChildren(chemainChild);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
}
Here's my trick. The purpose of having an myReff.addValueEventListener(new ValueEventListener()inside another myReff.addListenerForSingleValueEvent(new ValueEventListener() is to only execute onDataChange if my array from database has been changed. But the problem is that it's not the case.
Here's what's print first : 1, 3, 2 instead of 1, 2, 3 like I'm expecting with my trick.
Can you help me ? Am I handling the problem in the wrong way ? How must I do to only execute my second function, in condition that my array has been changed ? How can I keep my code waiting for changes in my database before executing something else ?
Hope you have understood me and feel free to ask me question if you doesn't understand something in my problem.
Change this:
myReff.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//this will be executed only if my array is changed (So only if my other function have been correctly executed
setAnotherArray(array_from_database);
System.out.println("3");
}
to this:
final FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myReff = database.getReference();
myReff.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DatabaseReference ref2 = database.getReference();
//Take the array from my database (gived in parameter)
final ArrayList<Integer> array = array_from_database;
System.out.println("2");
array.set(0,3);
Map<String, Object> chemainChild = new HashMap<>();
chemainChild.put("server/user/",array);
myReff.updateChildren(chemainChild);
System.out.println("3");
}
Some code may be missing from the above, but you get the idea add the code that is in the method public void setArray_for_database(ArrayList<Integer> array_from_database){ for this to work.
Since onDataChange is asynchronous meaning the program will keep executing, even if data is still not retrieved then this is the only way.
The reason you get 1-3-2, is because of this:
It entered the first onDataChange
It printed "1"
It entered the second onDataChange that is inside the first.
It printed "3" since it is asynchronous, then when the data was retrieved
It called the method and printed "2"
So the best thing is to add the data in the method inside the onDataChange
The above will fix the asynchronous problem that you had in the question. But you really should denormalize your data.
Read this to learn more: https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html

Retrieving child value -firebase-

System.out.println(ref.child("mostafa_farahat22#yahoo.com").child("_email"));
*i`m trying to get a value of child but all time i get the URL of the value
how to get the value of this URL as i try by this code but it get me the URLi want to get the _email value.
You are looking at the concept from the wrong angle.
While using the ref.child("mostafa_farahat22#yahoo.com").child("_email") you are just simply pointing at a particular place in your database and nothing more.
If you want to retrieve the data in that particular place, consider these 2 ways.
First if you want to retrieve the data only once, you can do the following :
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
DatabaseReference mostafa = ref.child("Users").child("mostafa_farahat22#yahoo.com").child("_email");
mostafa.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String email = dataSnapshot.getValue(String.class);
//do what you want with the email
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
or maybe you want to retrieve the value in real time and use it in the same time that the database value is changed, all in the same time, whenever the value in changed, then you use this :
mostafa.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String email = dataSnapshot.getValue(String.class);
display.setText(email);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Note the difference between the two methods. First is only for one time retrieve and the second is for retrieving the data whenever the value is changed.
Just have in mind that the codes that i posted are just templates and may need to play with them a bit.
With ref.child("mostafa_farahat22#yahoo.com").child("_email") you are just setting the reference to the object. Take a look at the java firebase documentation to retrieve data.
To get the data you will need to set a listener for your reference
ref.child("mostafa_farahat22#yahoo.com").child("_email").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// data available in snapshot.value()
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});

Categories