Retrieve an ArrayList from Firebase - java

I have an ArrayList of Objects in Firebase and I would like to retreive it.
I have 2 array lists. One String and one Grade. When I try to use the array of objects it has a problem:
java.lang.ClassCastException: java.util.HashMap cannot be cast to com.example.gradecalculator.Grade
mDocRef:
private DocumentReference mDocRef = FirebaseFirestore.getInstance().document("myData/Arrays");
Uploading the arrays:
Map<String, Object> dataToSave = new HashMap<String, Object>();
dataToSave.put("StringsArray", stringGrades); // Save Strings Array
dataToSave.put("ObjectsArray", grades); // Save Objects Array
mDocRef.set(dataToSave).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "Document has been saved!");
Toast.makeText(getApplicationContext(), "List has been saved successfully!", Toast.LENGTH_SHORT).show();
Downloading the arrays:
mDocRef.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
isListEmpty = false;
if (documentSnapshot.exists()) {
Map<String, Object> dataToLoad = (HashMap<String, Object>) documentSnapshot.getData();
stringGrades = (ArrayList<String>) dataToLoad.get("StringsArray");
grades = (ArrayList<Grade>) dataToLoad.get("ObjectsArray");
for (Grade grade : grades) { // <------------Fails here
System.out.println(grade.toString());
}
First time I'm trying to use Firebase. It seems that it saves the data in the server successfully. Any advice?

The get method of DocumentSnapshot return a List of Map :
List<Map<String, Object>>
You can create another class with your List :
class GradeContainer{
private List<Grade> grades;
public GradeContainer(){}
public List<Grade> getGrades(){
return grades;
}
}
And use dataToLoad.toObject() :
grades = List<Grade> dataToLoad.toObject(GradeContainer.class).getGrades();
You can read this documentation for more informations :
https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/DocumentSnapshot?hl=en
And this tutorial :
https://medium.com/firebase-tips-tricks/how-to-map-an-array-of-objects-from-cloud-firestore-to-a-list-of-objects-122e579eae10

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

How to get a list of Strings from inside of a document Firestore

I have stored a list of Strings inside a document.i have given it a name("name") now i am trying to get it on the client side but do not know how to do it exactly. i can see that if my field is of type number i can use getLong("Fieldname") but i am unable to figure it out how to get back a list of type Strings.
My code so far
FirebaseFirestore getlistofbrands=FirebaseFirestore.getInstance();
getlistofbrands.collection(FireStoreConstants.COL_BRANDNAMESONLY).document("Brands").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
List<String> listofbrandsfromfirestore=queryDocumentSnapshots.getDocuments().toArray(String.class);
also tried this
List<String> listofbrandsfromfirestore=queryDocumentSnapshots.toObjects(String.class);
how i uploaded the data
Map < String, Object > docData = new HashMap < > ();
List < String > deviceNameList = new ArrayList < String > ();
deviceNameList.add("brand1");
deviceNameList.add("brand2");
deviceNameList.add("brand3");
deviceNameList.add("brand4");
docData.put("name", deviceNameList);
firebaseFirestore.collection("FireStoreConstants.COL_BRANDNAMESONLY")
.document("Brands").set(docData).addOnSuccessListener(new
OnSuccessListener < Void > () {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "Repository:onSuccess:");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "Repository:error" + e.toString());
}
});
Since you store the brand names in a single document, I doubt QuerySnapshot is the right class to get back. As far as I can see, you'll want to use getData() to get the Map<String, Object> that Firestore uses for your List:
getlistofbrands
.collection(FireStoreConstants.COL_BRANDNAMESONLY)
.document("Brands")
.get()
.addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d(TAG, "DocumentSnapshot data: " + document.getData());
Map<String, String> brandsMap = (Map<String, String>)documen.getData().getData("AllBrands");
List<String> brands = new LinkedList<String>();
for (String key: brandsMap.keySet()) {
brands.add(brandsMap.get(key));
}
// TODO: use the brands list
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
You might also want to try:
List<String> brands = brandsMap.value();
i used the code provided by #Frank van and used this function to cast my Object to a list of Strings
#SuppressWarnings("unchecked")
public static <T extends List<?>> T cast(Object obj) {
return (T) obj;
}
Object brandsobj = queryDocumentSnapshots.getData().get("AllBrands");
List<String> allbrands = cast(brandsobj);
You can check out this question post I had posted earlier. You can change from the ArrayAdapter that I have used to a List
AutoCompleteTextView data from Firestore
Hope it helps you.

Categories