Firebase dealing with nested data - java

Okay, say I've got the following FireBase database structure.
{
"2143" :
{
"Henk" : 6,
"message" : 1
}
}
With data being added as follows:
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("2143/message");//Testing code, would later be replaced with a session variable and a username variable.
myRef.setValue(1);//Again, mere testing code which sets the 'message' key to have value 1. The actual code is currently lacking as the program isn't entirely functional yet.
I now want to put the players and their respective scores into a leaderboard on an android app in android studio. When I'm trying to put them into a hashmap using the following code:
String code = "2143"; //This is would be the SessionID, it's currently static for testing purposes.
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference(code);
HashMap<String, String> leaderboardMap = new HashMap<>();
...
myRef.orderByValue().addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot)
{
leaderboardMap.put(dataSnapshot.getKey(), dataSnapshot.getValue().toString());
}
}
I get the following hashmap
key: 2143, value:{Henk=6, message=1}
However I expected the following:
key: Henk, value: 6
key: message, value: 1
Where's the error in my code, and how can I fix it?

You can convert the json string to HashMap and then use those values to display in leaderborad. Here is a function to convert json sring to map.
public static HashMap<String,String> jsonToMap(String t) throws JSONException {
HashMap<String, String> map = new HashMap<String, String>();
JSONObject jObject = new JSONObject(t);
Iterator<?> keys = jObject.keys();
while( keys.hasNext() ){
String key = (String)keys.next();
String value = jObject.getString(key);
map.put(key, value);
}
return map;
}

Related

How to read the nested maps from fireStore database from android

In the above image, I have a map that contains an arrays list of 2020, 2021, etc. I want to display the arrays data in RecyclerView. How to do that in android?
Also how to retrieve data if a map contains a list of maps. I'm able to get the documents with field names, but struggling with how to get maps with field names and data in that maps.
DocumentSnapshot's getData() method, returns an object of type Map<String, Object>. Since it's a Map, we can simply get the year and then iterate through the corresponding URLs, like in the following lines of code:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference subjectRef = rootRef.collection("subject");
DocumentReference politicalScienceRef = subjectRef.document("political science");
politicalScienceRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
List<String> urls = new ArrayList<>();
Map<String, Object> data = document.getData();
Map<String, Object> year = (Map<String, Object>) data.get("year");
for (Map.Entry<String, Object> entry : year.entrySet()) {
List<String> yearUrls = (List<String>) entry.getValue();
for (String url : yearUrls) {
urls.add(url);
}
}
for (String url : urls) {
Log.d("TAG", url);
}
} else {
Log.d("TAG", "No such document");
}
} else {
Log.d("TAG", "get failed with ", task.getException());
}
}
});
In the end, simply pass the urls list to an adapter, and display all those URLs into a RecyclerView.

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
}
}

How to Check Data is Inserted Successfully in Firebase in Array

I am inserting some data in Firebase database From json Response in an array with below code
JSONArray arr = new JSONArray(result);
String[] stocks = new String[arr.length()];
for(int i=0;i<arr.length();i++){
JSONObject obj = arr.getJSONObject(i);
mDatabase= FirebaseDatabase.getInstance().getReference().child("books");
atabaseReference newBid=mDatabase.push();
newBid.child("usr_id").setValue(obj.getString("user_id"));
newBid.child("usr_fullNme").setValue(obj.getString("first_name")+" "+obj.getString("last_name"));
newBid.child("usr_mobile").setValue(obj.getString("user_mobile"));
newBid.child("usr_avatr").setValue(obj.getString("src"));
}
How can i check if above operation is successful or not
You can use a Hashmap and do the following:
Map<String, Object> userValues = new HashMap<>();
userValues.put("usr_id", obj.getString("user_id"));
userValues.put("usr_fullNme",obj.getString("first_name")+" "+obj.getString("last_name"));
userValues.put("usr_mobile", obj.getString("user_mobile"));
userValues.put("usr_avatr", obj.getString("src"));
Then use setValue():
mDatabase= FirebaseDatabase.getInstance().getReference().child("books");
String newBid = mDatabase.push().getKey();
mDatabase.child(newBid).setValue(userValues, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
System.out.println(databaseError);
}
});
From the docs:
public void setValue (Object value, DatabaseReference.CompletionListener listener)
Set the data at this location to the given value. Passing null to setValue() will delete the data at the specified location. The native types accepted by this method for the value correspond to the JSON types:
Boolean
Long
Double
String
Map
List

How to add data to the array of hash map in the document using Firestore?

I want to add data to the existing array without overwriting. And inside each document, I have an array of HashMap. I am trying to add data to the existing one. Kindly check the below code and shed some light.
public void createNewCase(){
Map<String, String> caseInfo = new HashMap<String, String>();
caseInfo.put("chief_complaint", chiefComplaintET.getText().toString());
caseInfo.put("facility", facilityET.getText().toString());
caseInfo.put("location", locationET.getText().toString());
caseInfo.put("assigned_provider", assignProviderET.getText().toString());
caseInfo.put("referring_provider", referringProviderET.getText().toString());
caseInfo.put("admit_date", adminDateET.getText().toString());
caseDictionary.add(caseInfo);
final String patientID = sharedPrefHelper.getStr("patient_id");
db.collection("patients").whereEqualTo("patient_id", patientID).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
private static final String TAG = "New Case Creation" ;
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<HashMap<String,String>> list = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
patient patient = new patient();
list = (List) document.get("patient_case");
for (HashMap<String, String> item:list) {
caseDictionary.add(item);
}
}
System.out.println(caseDictionary);
HashMap<String, Object> uploadData = new HashMap<>();
uploadData.put("patient_case", caseDictionary);
DocumentReference caseRef = db.collection("patients").document(patientID); // am stuck here
}else{
Log.w(TAG, "Error getting documents.", task.getException());
Toast.makeText(NewCase.this, "Something bad happened", Toast.LENGTH_SHORT).show();
Helper.m_Dialog.hide();
}
}
});
}
Edit 1
Below code deleting old data and adding new data. I need to append.
final String patientID = sharedPrefHelper.getStr("patient_id");
final CollectionReference collectionReference = db.collection("patients");
collectionReference.whereEqualTo("patient_id", patientID).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
Toast.makeText(NewCase.this, task.getResult().toString(), Toast.LENGTH_SHORT).show();
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Map<Object, Object> map = new HashMap<>();
map.put("patient_case", caseInfo);
collectionReference.document(document.getId()).set(map, SetOptions.merge());
}
}else{
Toast.makeText(NewCase.this, task.getResult().toString(), Toast.LENGTH_SHORT).show();
}
}
});
As I see in your screenshot, in your patients collection you have documents that contain an array that holds maps (objects). In order to be able to update those maps that exist within your array you should create a Map object that corresponde to your exact document structure and use DocumentReference's set(Object data, SetOptions options) method for that. So pass as the first argument the map and as the second argument SetOptions.merge(). You can find a simpler example in my answer from the following post:
Firestore firebase Android search and update query
This is one of my example
i have done it like this
List<Map> history = List();
History historyObj = History(typee, name, timeStamp, pointsBefore, points, itemPoints);
history.add(historyObj.toMap());
//Firesore collection object
CollectionReference child = _firestore.collection('children');
//Firesore document object
DocumentReference docRef = child.doc(selectedChild.childId);
// "history" is your "patient_case"
docRef.update({"history": FieldValue.arrayUnion(history)}).then(
(value) => print("Update done"));
History is one of my class
History class includes method toMap() which converts all history class variables and its values to 'Key' : 'value' form like this
Map<String, dynamic> toMap() => {
"type": type,
"name": name,
"timestamp": timestamp,
"points_before": points_before,
"points_after": points_after,
"points_affected": points_affected,
};

Posted data missing using firebase

I'm trying to insert some data into my firebase but encountered the following error, the 2nd data is missing. Here are the code:
Firebase.setAndroidContext(this);
Button btnSave = (Button) findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
//Creating firebase object
Firebase ref = new Firebase(Config.FIREBASE_URL);
//Getting values to store
String name = mName.getText().toString().trim();
String address = mAddress.getText().toString().trim();
String latlng = mLatLng.getText().toString().trim();
//Creating Person object
FM_Spots spots = new FM_Spots();
//Adding values
spots.setName(name);
spots.setAddress(address);
spots.setLatLng(latlng);
//Storing values to firebase
//ref.child("FM_Spots").setValue(spots);
Firebase newRef = ref.child("FM_Spots").push();
newRef.setValue(spots);
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage().toString(), Toast.LENGTH_SHORT).show();
}
}
});
}
I only have 2 fields which are name and the address is having data from the last field (latlng). Please advise, thank you.
-sea-
When you said "2nd data" you meant that the second field of the writable object is missing, right?
If so, you can use updateChildren(Map map) method instead of setValue() to specify fields you want to write directly:
newRef.updateChildren(convertFMSpotsToMap(spots));
where convertFMSpotsToMap() is something like this:
private static Map<String, Object> convertFMSpotsToMap(#NonNull FM_Spots spots) {
HashMap<String, Object> map = new HashMap<>();
map.put("name", spots.getName());
map.put("address", spots.getAddress());
return map;
}

Categories