Get number of unique children in an Array/dataSnapshot? - java

The code below allows me to get the number of children inside the dataSnapshot.
public void onDataChange(DataSnapshot dataSnapshot) {
long numberChildren = dataSnapshot.getChildrenCount();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
My question is how do I get the number of unique children? Something like this would work perfectly: dataSnapshot.getUniqueChildrenCount()

Approach without using set:
ArrayList<String> values=new ArrayList<String>();
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
String children = childDataSnapshot.getValue(String.class);
if (!values.contains(children)) {
values.add(newValue);
}
}
approach using set:
Set<String> set = new HashSet<String>();
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
String children = childDataSnapshot.getValue(String.class);
set.add(children);
}

Related

Firebase - (DataSnapshot with multiple child nodes user unique key ) -Null Object Refrence

I have number of Medicines corresponding to each patient unique key. i am facing trouble to retrieve all of medicine data of the patient Here is my database structure.
{
"Medicine" : {
"-LnRyr-3szcVYVtr_d4m" : {
"Med1" : {
"dosage" : "1+1+1",
"medname" : "Panadol",
"time" : "After Every Meal"
},
"Med2" : {
"Mmedname" : "Raisik",
"med2dosage" : "1+1+1",
"med2time" : "after every meal 1 week"
}
}
}
}
Code
databaseReference = FirebaseDatabase.getInstance().getReference("Medidine");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot requestSnapshot: dataSnapshot.getChildren()) {
DataSnapshot ds = requestSnapshot.child("Med1");
for (DataSnapshot medicinesnapshot: ds.getChildren()) {
String MedicineName = medicinesnapshot.child("medname").getValue(String.class);
String MedDosage = medicinesnapshot.child("dosage").getValue(String.class);
String medtime = medicinesnapshot.child("time").getValue(String.class);
marray.add(MedicineName+MedDosage+medtime);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
For a patient with patientId=-LnRyr-3szcVYVtr_d4m;
then you can get all medicines related to that patient like this
String patientId="-LnRyr-3szcVYVtr_d4m";
FirebaseDatabase.getInstance().getReference().child("Medicine").child(patientId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
MedicineData medicineData = snapshot.getValue(MedicineData.class);
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

how to get all child nodes from firebase database?

this is my structure. i am trying to code a scoreboard for my app but i cant get the username & score. i want to safe that username & score in a sorted list to get the top 10.
this is my code: i onle get the usernames.
databaseReference = FirebaseDatabase.getInstance().getReference("Users");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Userlist = new ArrayList<String>();
// Result will be holded Here
for (DataSnapshot dsp : dataSnapshot.getChildren()) {
for (DataSnapshot as : dataSnapshot.getChildren()) {
String userkey= as.getKey();
Userlist.add(userkey); //add result into array list
}
}
un.setText(Userlist.get(2));
}
#Override
public void onCancelled(DatabaseError error) {
}
});
Try the following:
databaseReference = FirebaseDatabase.getInstance().getReference("Users");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Userlist = new ArrayList<String>();
// Result will be holded Here
for (DataSnapshot dsp : dataSnapshot.getChildren()) {
String userkey = dsp.getKey();
String scores = dsp.child("scorehigh").getValue().toString();
Userlist.add(userkey); //add result into array list
}
}
un.setText(Userlist.get(2));
}
#Override
public void onCancelled(DatabaseError error) {
}
});
The reference is at Users then you need to loop twice to be able to access the attributes scorehigh and username

Retrieve cross objects child from Firebase Database

I am trying to get weight and quantity from Cat1 where item_name, date and branch are same in Cat2 in Firebase Realtime DB. But I don't know how to check conditions for that.
JSON
"Cat1" : {
"-LBBWypuYLVn-aDYWK-N" : {
"branch" : "b1",
"date" : "28/Apr/2018",
"weight" : "46",
"item_name" : "item1",
"quantity" : "20"
},
"-LBBZKUlEJB-HdiKftoj" : {
"branch" : "b2",
"date" : "28/Apr/2018",
"weight" : "112",
"item_name" : "item2",
"quantity" : "16"
}
},
"Cat2" : {
"-LBBWQcC3acYk-OOiX3T" : {
"branch" : "b1",
"date" : "28/Apr/2018",
"item_name" : "item1",
"weight" : "2.7",
"quantity" : "20"
}
}
So far I have done the following:
mFishQuery = mFishRef.orderByChild("date").equalTo(mawStock.getDate());
// mFishQuery = mFishRef.orderByKey();//.equalTo(mawStock.getDate());
// Query fishWeight = mFishQuery.orderByChild("item_name").equalTo(mawStock.getItem_name()).getRef().orderByChild("quantity").equalTo(mawStock.getQuantity());
mFishQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mWeightF = (Double) dataSnapshot.child("fish_weight").getValue();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mFishRef.child("date").equalTo(mawStock.getDate()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Try the following:
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Cat2");
ref.orderByChild("item_name").equalTo("item1").addSingleValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String date=datas.child("date").getValue().toString();
DatabaseReference refer=FirebaseDatabase.getInstance().getReference().child("Cat1");
refer.orderByChild("date").equalTo(date).addSingleValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//retrieve data
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
When you query, you can only use one child so one orderByChild() or orderByKey()
So, here you have the datasnapshot at child Cat2 then you query where item_name=item1 and you retrieve the date from the database.
Then you add a nested listener and do a query where date= date_retrieved, and retrieve the data of Cat1.
Basically, you just have to do enough itr.next() until the iterator is at the nth position (where n is the random number from nextInt()) and then you can simply get the Object you want with getValue(), the example below should show it well:
Solution to get random generated keys.
questionsRef = FirebaseDatabase.getInstance().getReference().child("questions").child("DE");
questionsRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int questionCount = (int) dataSnapshot.getChildrenCount();
int rand = random.nextInt(questionCount);
Iterator itr = dataSnapshot.getChildren().iterator();
for(int i = 0; i < rand; i++) {
itr.next();
}
childSnapshot = (DataSnapshot) itr.next();
question = childSnapshot.getValue(Question.class);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Finally I solved the problem with the help of #Peter Hadad's answer with some modification in his answer.
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Cat1");
ref.orderByChild("item_name").equalTo("item1").addSingleValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas : dataSnapshot.getChildren()){
DatabaseReference refer=FirebaseDatabase.getInstance().getReference().child("Cat1");
refer.orderByChild("date").equalTo(date).addSingleValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (Datasnapshot ds : dataSnapshot) {
List<Datasnapshot> list = new ArrayList<>();
list.add(ds);
//compare data and apply logic
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});

I want to delete the Firebase database child, but I can't

I want to delete the Firebase database child with this follow code when I click the first item in a list in an app, but I can't. What's wrong?
Query removeCalendar = mCalendarDatabaseReference.limitToFirst(1);
removeCalendar.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String remCal = dataSnapshot.toString();
mCalendarioDatabaseReference.child(remCal).removeValue();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Firebase Queries return a list of possible locations where the query might be satisfied, you'd need to iterate through your dataSnapshot to access those locations. Moreover, this :
String remCal = dataSnapshot.toString();
is not going to print the String value of this snapshot. If you want to get the string value of a dataSnapshot it should be:
String remCal = dataSnapshot.getValue(String.class);
If you want to get the reference of a datasnapshot just use getRef(), you don't have to access the original reference.
Query removeCalendar = mCalendarDatabaseReference.limitToFirst(1);
removeCalendar.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
child.getRef().setValue(null); //deleting the value at this location. You can also use removeValue()
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I solve the problem with this code:
Query removerCalendario = mCalendarioDatabaseReference.limitToFirst(1);
removerCalendario.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
ds.getRef().removeValue();
}
}
You can do mCalendarioDatabaseReference.child(remCal).setValue(null);

How to handle results from Firebase seeing that its aynchronous

How do I return combinedFoodItem from the code below. I have been using firebase for less than a week now and I still find this confusing. The summary is:
Food contains name and categoryId (which is from the FoodOption model)
public void getFoodItems() {
//get all the food options for the selected venue
final List<FoodItem> combinedFoodItem = new ArrayList<>();
filterRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
final FoodOption foodOption = dataSnapshot1.getValue(FoodOption.class);
final List<Food> foodList = new ArrayList<>();
meniItemFilter = menuItemReference.orderByChild("categoryId").equalTo(foodOption.getKey());
meniItemFilter.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot2 : dataSnapshot.getChildren()) {
Food food = dataSnapshot2.getValue(Food.class);
foodList.add(food);
}
FoodItem foodItem = new FoodItem(foodOption.getFoodCategory(), foodList, R.drawable.ic_banjo);
combinedFoodItem.add(foodItem);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
as firebase works in a reactive manner you can't return elements but listen for changes of them. You can define your combinedFoodItem outside the function (this is, for instance, as a class field) and then add the elements to the list (or clear the list every time the data changes if you want to reset the list this depends on the behavior of your list)

Categories