How to loop through data in Map with Java - java

Fetched data from Firebase database and added as a Map object. now I need to loop through every key's value so I can get child data from it. here are my both Database structure and the code am using:
public void gettingStationDate() {
// Read from the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("station");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
Log.e(TAG, "Value is: " + map);
assert map != null;
for (Map.Entry<String, Object> entry : map.entrySet()) {
Log.e("The Result", entry.getKey() + "/" + entry.getValue());
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
}
this code give me the result as key, value like this : -LlRGuwBNe2-S_MHn2DW/{station_longitude=30.854333, station_name=الاصلاح الزراعى, station_latitude=29.313847, station_geohash=stjyy07mw14h} Now what i need to do is to get the inner values of the shown values , as statin_longitude , station_name etc..

Since each child node that you have is another JSON object, each value in your Map is another Map. And since all your values are strings, this time it's a Map<String,String>.
So to get the specific values, you'd do something like:
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
assert map != null;
for (Map.Entry<String, Object> entry : map.entrySet()) {
Log.i("The key", entry.getKey());
Map<String,String> values = (Map<String,String>) entry.getValue();
Log.i("station_name", map.get("station_name"));
}
}
It is more idiomatic to use the DataSnapshot's method to accomplish the same:
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot stationSnapshot: dataSnapshot.getChildren()) {
Log.i("The key", stationSnapshot.getKey());
Log.i("station_name", stationSnapshot.child("station_name").getValue(String.class));
}
}

Related

Check duplicate data on Realtime Database with Java on Android Studio

I'm developing an app:
In my realtime database I have this structure
But some keys have the same data and it's a duplicate like this:
In my Android Studio project I code this function but only retrieve the data but no check the duplicates:
private void deleteIfAreDuplicateData() {
List<Order> orderList = new ArrayList<>();
FirebaseDatabase.getInstance().getReference(Common.ORDER_REF)
.orderByKey()
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
ArrayList<Object> numeroDeOrden = new ArrayList<>();
String datos;
String pagoFinal, tiempo, idUsuario, nombreUsuario;
boolean exists = false;
for (DataSnapshot orderSnapshot : dataSnapshot.getChildren()) {
Map<String, Object> model = (Map<String, Object>) orderSnapshot.getValue();
pagoFinal = String.valueOf(orderSnapshot.child("finalPayment").getValue());
tiempo = String.valueOf(orderSnapshot.child("orderTime").getValue());
idUsuario = String.valueOf(orderSnapshot.child("userId").getValue());
nombreUsuario = String.valueOf(orderSnapshot.child("userName").getValue());
datos = (String) orderSnapshot.getKey();
numeroDeOrden.add(datos);
for (int i = 0; i < numeroDeOrden.size(); i++) {
if (model.get("finalPayment").equals(pagoFinal) && model.get("orderTime").equals(tiempo)) {
exists = true;
}
}
}
if(exists)
{
Toast.makeText(getContext(), "Tienes ordenes repetidas ", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
How can I check for duplicate in the database and when I have the duplicates remove only one of the 2 values (?)
If you want to prevent duplicate values, use those values as the keys for the data. So in your case, if you want the combination of all property values to be unique, combine all of those values into a single string and use that as your key.
You'll want to remove or encode any characters that are not allowed in keys, so ., $, [, ], #, and /, from the key.
In addition, if the key becomes longer than the maximum key length of 768 characters, you'll want to reduce it down to size too with a hash function or by simply truncating the string. See my answer here for some more info on that: Firebase Error: First argument has a key path longer than 768 Bytes
You can have a list of your model saved in your activity (or typically in ViewModel as a static member):
pubic static List<Map<String, Object>> modelList;
Then for each change in data you can add only the new data to the model by checking if exists using contains() method:
for (DataSnapshot orderSnapshot : dataSnapshot.getChildren()) {
Map<String, Object> model = (Map<String, Object>) orderSnapshot.getValue();
if (!modelList.contains(model)) {
modelList.add(model);
// Add your rest of code for the incoming new/change of data
}
}

Springboot + ReactJS + Firebase's Realtime Database

Back-end: Springboot
Front-end: ReactJS
CloudRepo: Firebase Realtime Database
I have a Springboot application that GETs data from the Firebase Realtime Database.
This data is then served via a GET request from reactJS.
I get the JSON object in reactJS as :
What I am trying to do is to map the firebase snapshot to a Java Collection. Here is What I have done so far:
DatabaseReference ref = FirebaseService.getFirebaseDatabase().getReference("/devices/device1");
ref.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
DeviceData message = messageSnapshot.getValue(DeviceData.class);
System.out.println(message);
}
Map<String, DeviceData> document = (Map<String, DeviceData>) dataSnapshot.getValue();
setUpdatedDocumentData(document);
}
public void onCancelled(DatabaseError error) {
System.out.print("-----Error-----:\n" + error.getMessage());
}
});
My POJO looks like this:
public class DeviceData {
String sensor_1;
String sensor_2;
public DeviceData() {}
public DeviceData(String sensor_1, String sensor_2) {
this.sensor_1 = sensor_1;
this.sensor_2 = sensor_2;
}
public String getSensor_1() {
return sensor_1;
}
public void setSensor_1(String sensor_1) {
this.sensor_1 = sensor_1;
}
public String getSensor_2() {
return sensor_2;
}
public void setSensor_2(String sensor_2) {
this.sensor_2 = sensor_2;
}
#Override
public String toString() {
return "DeviceData{" +
"sensor_1='" + sensor_1 + '\'' +
", sensor_2='" + sensor_2 + '\'' +
'}';
}
}
I am getting null in my sensor_1 and sensor_2 log. How can I map the above firebase structure to a collection?
Under each /devices/$device node, you have two nested levels:
For the date
For the time.
Your code only has once loop over the children of the device node, so your messageSnapshot variable is actually a snapshot with all data for all timestamps for a specific date.
To handle your structure correctly, you need two nested loops:
DatabaseReference ref = FirebaseService.getFirebaseDatabase().getReference("/devices/device1");
ref.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dateSnapshot: dataSnapshot.getChildren()) {
for (DataSnapshot timeSnapshot: dataSnapshot.getChildren()) {
DeviceData message = timeSnapshot.getValue(DeviceData.class);
System.out.println(message);
}
}
Map<String, DeviceData> document = (Map<String, DeviceData>) dataSnapshot.getValue();
setUpdatedDocumentData(document);
}
public void onCancelled(DatabaseError error) {
System.out.print("-----Error-----:\n" + error.getMessage());
}
});
If you only care about the latest timestamp on the latest date, you can reduce the amount of data you read from the database by only getting the latest date:
DatabaseReference ref = FirebaseService.getFirebaseDatabase().getReference("/devices/device1");
ref.orderByKey().limitToLast(1).addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dateSnapshot: dataSnapshot.getChildren()) {
for (DataSnapshot timeSnapshot: dataSnapshot.getChildren()) {
DeviceData message = timeSnapshot.getValue(DeviceData.class);
System.out.println(message);
}
}
Map<String, DeviceData> document = (Map<String, DeviceData>) dataSnapshot.getValue();
setUpdatedDocumentData(document);
}
public void onCancelled(DatabaseError error) {
System.out.print("-----Error-----:\n" + error.getMessage());
}
});
You'll still have to read all timestamps for that date, but at least you're now only reading data for the most recent day.

How do I query Firestore Array Value?

How can I Query the Array dates with the month value?
String monthString = "12";
Query queryZero = db.collection("Users").document(mCurrentUser).collection("Dates").whereArrayContainsAny("dates", ???);
What do I have to put where the '???' to retrieve dates with the dd/MM/yyyy <- /MM/ value is equal to the monthString?
Firestore at the moment does not support this kind of query. But, a possible workaround is to store additional array of months in your document and perform:
db.collection("Users").document(mCurrentUser).collection("Dates").whereArrayContains("months", "12");
Another solution is similar to #Ruyut's answer. But this would retrieve all the documents in the collection and you would have to perform the filtering in the client-side which could possibly degrade performance if you have thousands of documents.
FirebaseFirestore.getInstance().collection("Users")
.get()
.addOnSuccessListener(
new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
for (DocumentSnapshot ds : documentSnapshots.getDocuments()) {
// same code as #Ruyut's answer
}
}
}
);
public static void getData(){
DatabaseReference database = FirebaseDatabase.getInstance().getReference("Users").child(mCurrentUser).child("Dates");
database_course.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String key = ds.getKey(); //7UE......
HashMap<String, ArrayList<String>> datesHashMap = ds.get(key);
for(int i =0;i<datesHashMap.get("dates").size();i++){
String date = datesHashMap.get("dates").get(i);//08/12/2019
if (date.substring(3,5).equals("12")){
//put your code
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}

Why does my firebase database child return null?

I am working with firebase database and i was trying to get the value of a child using this code below and may System.out.println(MyCredit.toString()); is always returns null: Please see my firebase database
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users");
ref.addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Get map of users in datasnapshot
CollectCredits((Map<String,Object>) dataSnapshot.getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
//handle databaseError
}
});
private void CollectCredits(Map<String,Object> users) {
MyCredit = new ArrayList<>();
//iterate through each user, ignoring their UID
for (Map.Entry<String, Object> entry : users.entrySet()){
//Get user map
Map singleUser = (Map) entry.getValue();
//Get Credit field and append to list
MyCredit.add((Long) singleUser.get("Credit"));
Toast.makeText(MainActivityCustonlistViewnew.this, "Credit : " +String.valueOf(MyCredit), Toast.LENGTH_SHORT).show();
}
System.out.println(MyCredit.toString());
}
Try this:
private void CollectCredits(DataSnapshot dataSnapshot) {
MyCredit = new ArrayList<>();
//iterate through each dataSnapshot
for (DataSnapshot d1 : dataSnapshot.getChildren()){
MyCredit.add(d1.getValue());
}
}
Let me give you some suggestions, Try to check your firebase database path both the root and child path because some time you did everything correctly but the path you specified to your Database reference which is not referring to the correct path. So it can produce the same result what are getting right now.

Retrieve String from Realtime Firebase Database

I am trying to retrieve a string from the database but everytime I try it shows an error which says "Failed to convert value of type java.util.HashMap to String" a guy on Stackoverflow had my same problem, ii followed the answer that helped him but it's still not working for me
I tried to map the code as an hashmap but it keeps showing me error
This is the model
public ButtonInformationSend(String testoNotifica) {
TestoNotifica = testoNotifica;
}
public String getTestoNotifica() {
return TestoNotifica;
}
public void setTestoNotifica(String TestoNotifica) {
this.TestoNotifica = TestoNotifica;
}
and this is the code
myRef.addValueEventListener(new ValueEventListener() {
#Override public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
ButtonInformationSend buttonInformationSend = dataSnapshot.getValue(ButtonInformationSend.class);
creaNotifica(buttonInformationSend);
}
#Override public void onCancelled(#NonNull DatabaseError databaseError) {}
});
the error i get is this Failed to convert value of type java.util.HashMap to String
If you have this database:
Users
id
name : peter
Then the variable myRef should be referencing the node id to be able to retrieve a String, if myRef is referencing the root node then you would get the error:
Failed to convert value of type java.util.HashMap to String
Therefore you should do the following:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users");
ref.child(id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("name").getValue(String.class);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
In Java, you cannot directly convert a Hashmap to a string as they are two different types.
DataSnaphhot.getValue()
returns a hashmap of all the data found at your reference, if your reference points to a node of data in the database. What you need to do is get the hashmap from the data snapshot and then get the relevant data needed from that hashmap, Here is an example of that:
HashMap<String, Object> data = (HashMap<String,Object>) dataSnapshot.getValue();
try {
String value1 = (String) data.get("Value1");
String value2 = (String) data.get("Value2");
String value3 = (String) data.get("Value3");
} catch (Exception e) {
e.printStackTrace();
}
Hope this helps.

Categories