How to read the nested maps from fireStore database from android - java

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.

Related

Error retrieving data from Cloud Firestore database

I sent a Map<String, LatLng> to my Cloud Firestore database. Now, I want to retrieve the data as a Map. Then, I want to send that Map to my fragment so that the fragment can plot the LatLng on a google map.
Here's what I've done:
I successfully retrieved the data from the database, but the error comes in the fragment, where I want to get the LatLng from the Map.
How I retrieve the data:
MapsActivity:
Source source = Source.DEFAULT;
pinColRef.get(source)
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
ArrayList arrayOfPins = new ArrayList<java.util.Map>();
arrayOfPins.add(document.getData());
Log.i(TAG, document.getData().toString());
}
}
}
});
As you see, I retrieve the data and then use getData() to get the Map I sent. The Log.i statement successfully shows the data from the database as a Map.
So, I send that data to the fragment.
Here's how I did that:
MapsActivity:
public ArrayList getPinData() {
return arrayOfPins;
}
Fragment:
MapsActivity activity = (MapsActivity) getActivity();
ArrayList arrayOfPins = activity.getPinData();
How I try to plot the LatLng from the database (in the MapReadyCallback in the Fragment):
for (java.util.Map ploc : arrayOfPins) {
LatLng pCoord = ploc.get("Location");
map.addMarker(new MarkerOptions()
.position(pCoord)
.title("Pin"));
}
The first error comes on the java.util.Map ploc:
error: incompatible types: Object cannot be converted to Map
Then, the other error is on LatLng pCoord = ploc.get("Location").
Here is a picture of my Firestore Database:
I thought that when you use getData() it returns the fields of the document as a Map.
So, why are the elements in arrayOfPins not Maps?
I thought that when you use getData() it returns the fields of the document as a Map.
Indeed, QueryDocumentSnapshot's getData() method returns a Map<String, Object> object. However, to get the data under Location property, you should explicitly call .get("Location") on the QueryDocumentSnapshot object, like in the following lines of code:
pinColRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Map<String, Object> map = (HashMap<String, Object>) document.get("Location");
if (map != null) {
Log.d("TAG", map.get("latitude") + ", " + map.get("longitude"));
//Add the markers on the map
}
}
} else {
Log.d(TAG, task.getException().getMessage());
}
}
});

How can I retrieve a specific field from a map in Cloud Firestore using Android?

This is a part of data saved in firebase Firestore:
How can I get (fName) from (newFriend0) in Java?
This is part of the code. It gave the entire map. I want just a specific field such as ("jem" for (fName))
Map<String, Object> map = document.getData();
for (Map.Entry<String, Object> entry : map.entrySet()){
if (entry.getKey().equals("Friends")){
f=document.getString("FName");////not worked
Log.d("TAG", entry.getValue().toString());
}
}
Edit: July, 16th 2201
As a matter of fact, there is a simpler way of getting that data:
How to map an array of objects from Cloud Firestore to a List of objects?
Seeing that your code is in Java, please see the solution below:
FirebaseFirestore.getInstance().collection("coll").document("9999").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Map<String, Object> friendsMap = document.getData();
for (Map.Entry<String, Object> entry : friendsMap.entrySet()) {
if (entry.getKey().equals("Friends")) {
Map<String, Object> newFriend0Map = (Map<String, Object>) entry.getValue();
for (Map.Entry<String, Object> e : newFriend0Map.entrySet()) {
if (e.getKey().equals("newFriend0")) {
Map<String, Object> fNameMap = (Map<String, Object>) e.getValue();
for (Map.Entry<String, Object> dataEntry : fNameMap.entrySet()) {
if (dataEntry.getKey().equals("fName")) {
Log.d("TAG", dataEntry.getValue().toString());
}
}
}
}
}
}
} else {
Log.d("TAG", "No such document");
}
} else {
Log.d("TAG", "get failed with ", task.getException());
}
}
});
The result in your logcat will be:
jem
Didn't see the name of your collection in the screenshot, so I named it simply coll but you should definitely change it to the correct one.
Basically you need to perform 2 steps, retrieve the document data with one of the provided libraries and then manipulate the resulting map object with the means of your programming language.
Here is a simple Nodejs example getting 'fName':
let docRef = db.collection('<collection_name>').doc('9999');
docRef.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
console.log('Document data:', doc.data().Friends.newFriend0.fName);
}
})
.catch(err => {
console.log('Error getting document', err);
});
Firestore document is in JSON format thus we can just convert the documentSnapshot.getData() to String first then to JSON so it will be more easier to access the Map objects data without needing too many loops/iteration. Another way is to do it like this documentSnapshot.getData().get("get_only_map_key_to_be_converted_as_JSON") convert it to string then to JSON as well. The possible remaining problem is if you store url in your document's map object which will have a problem as those link needs to be unescaped to become a valid JSON though I haven't tried that scenario yet in Android Java.

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 data from a sub-collection in Firestore on Android?

I have my Firestore database in the following way:
Image Database Firestore
I been try this to get the value of sub-collection:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
DocumentReference bulletinRef = rootRef.collection("facultades").document("3QE27w19sttNvx1sGoqR").collection("escuelas").document("0");
bulletinRef.get()
.addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
Log.d(LOG_TAG, "RESULTADO DE LA CONSULTA" + "===" + document.getData());
}
}
});
But this does return null:
Image result
Please help me.
You are getting null because escuelas is not a subcollection, it is an array that holds objects of type HashMap. So the following line of code:
DocumentReference bulletinRef = rootRef.collection("facultades").document("3QE27w19sttNvx1sGoqR")
.collection("escuelas").document("0");
Will never work. If you want to get the data within the escuelas array, please note that array type fields arrive from the Cloud Firestore database as a List of maps. So please use the following lines of code:
rootRef.collection("facultades").document("3QE27w19sttNvx1sGoqR").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
List<Object> list = (List<Object>) document.get("escuelas");
//Iterate throught the list and get the data
}
}
}
});
Please also note that while iterating, each element that you get from the list is of type HashMap. So you'll need to iterate again to get the corresponding data within each HashMap object.
Thanks, this really helped me, I used this code to iterate
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
rootRef.collection("facultades").document("3QE27w19sttNvx1sGoqR")
.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
List<Object> list = (List<Object>) document.get("escuelas");
//Iterate throught the list and get the data
Map<String, String> map = new HashMap<>();
map.put("key2", list.toString());
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
}
});
this is the result: Image result
But i feel confused, how ca I get just this:
image database
Facultades> all documents> escuelas > name

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