I'm trying to retrieve and store the values within this Map in my Firestore. The way I have my Firestore set up is like so:
I've found a way to retrieve other fields within my Firestore database but when trying to access map values like so:
horsepowerTextView.text = result.data?.getValue("Horsepower").toString()
it crashes the application and gives me an error saying that "Key Horsepower is missing in the map".
Can you please tell me how I would be able to get the values within Cars?
The following picture shows Firestore layout and code:
I've tried this link (how to read mapped data from firestore in kotlin) but when creating the map it only retrieves the topmost variable in the document NOT a part of the Map which would be the values firstName and lastName:
I actually answered that question, but your use case is totally different than the linked one. Why? Simply because "Cars" is an array of maps (custom objects). If you only want to get the value of the "Horsepower" field, then simply use the following lines of code:
val db = Firebase.firestore
val usersRef = db.collection("users")
usersRef.document("TwbJb27eFL3HAS1xLhP1").get().addOnCompleteListener {
if (it.isSuccessful) {
val data = it.result.data
data?.let {
val cars = data["Cars"] as List<*>
for (car in cars) {
val carMap = car as Map<*, *>
val horsepower = carMap["Horsepower"]
Log.d(TAG, "$horsepower")
}
}
}
}
The result in the logcat will be:
120
If you want however to map the "Cars" array into a list of custom objects, then I recommend reading the following resource:
How to map an array of objects from Cloud Firestore to a List of objects?
Related
I have a problem because I want to get every languages1 from all Decks. I cannot get there. I tried like this:
document.data["languages"][1] <--- error
Only works this:
document.data["languages"]
But this above returns me all languages, but I want to get only second language from the array and do distinct from this list. How to get this? Now my code looks like this:
val documents = db.collection("Decks")
.get()
.await()
val languages = documents?.mapNotNull { document ->
document.data["languages"] as String
}
Any tips?
Here is how looks my database:
This is not how to deal with that type of field:
document.data["languages"][1]
DocumentSnapshot#getData() method, returns an object of type Map<String, Any>. When you try to read the value that corresponds to a specific key, you actually don't know what kind of object is returned. It can be an array or any other object that is one of the supported data types. Seeing your document, the "languages" field is indeed an array, so you need to cast the object to a List. In order to get the second element, please use the following line of code:
val en = (document.data["languages"] as List<String>)[1]
If you try to log this value, you'll get as result:
en
Firestore Database Accessing Code in Activitymain.xml
db.collection("billNo") // I think want to add some code here to get the data!!//
.get()
.addOnSuccessListener {
user.clear()
for (document in it) {
user.add(User(
document.id,
document.data.get("billNo").toString().toInt(),
document.data.get("date").toString(),
document.data.get("name").toString(),
document.data.get("amount").toString().toInt(),
document.data.get("payment").toString()
)
)
}
Database Structure
#Parcelize
data class User(
val id: String,
val billNo: Int,
val date: String,
val name: String,
val amount: Int,
var payment:String
) : Parcelable
I Add billNo, date, name, amount, paid_or_unpaid data into the FIREBASE DATABASE. So when I click on searching I want to get details of the selected month in the RecyclerView. All RecyclerView code and other things working perfectly fine. Only I want to retrieve the data of the selected month.
When I click on the Respective Month & Year in the Following Activity (Screenshot is provided below) I want to get the details of bills in the respective month from the FIREBASE FIRE STORE DATA Base. I tried a lot. but I can't find a solution. I'm doing my project on Android Studio with KOTLIN programming Language.
There is no LIKE operator in Firestore. So a query like this:
"SELECT * from tablename WHERE date LIKE %$month-$year%"
Is actually not possible. Because your "date" field is actually a String, when using small data sets you might consider using:
Is there a way to search sub string at Firestore?
Or you can try using the newly Firebase Extension announced at Google I/O 2021 called:
Search with Algolia
Or directly in code:
Is it possible to use Algolia query in FirestoreRecyclerOptions?
However, there are two workarounds that can be used to achieve the same result. The first one would be to create another field in your User object called "monthYear". This property will hold a different value than the "date" property. For instance, if your "date" property holds the value of "03-May-2021", "monthYear" property will only hold the value of "May-2021". That been said, the Query will look like this in Kotlin:
val rootRef = FirebaseFirestore.getInstance()
val queryByMonthYear = rootRef.collection("billNo").whereEqualTo("monthYear", "May-2021")
The second solution would be to change the type of the "date" from String to Timestamp. Please see below how you can add a Timestamp to Firestore:
How to add a Timestamp in Firestore with Android?
It's in Java but you can simply convert it in Kotlin. Then, you can use a Query with a call to startAt(startDate) and endAt(endDate).
I added a JSON to firebase realtime database and when I retrieved it it all goes smooth until I add a new element to the list through the app and it transforms it on a Hashmap.
How can I mantain it as a list.
override fun onDataChange(p0: DataSnapshot) {
val database = p0.getValue(ListOfGamesJavaModel::class.java)!!
val lastUpdate = database.date
}
This works fine before I add new elements to list
val newGameRef = database.child("gamesList")
newGameRef.child(System.currentTimeMillis().toString()).setValue(game)
database.child("date").setValue("23-08-2019 20:32")
After that when I run the code to retrieve the list I get this error.
com.google.firebase.database.DatabaseException: Expected a List while deserializing, but got a class java.util.HashMap
Can you help me retrieve it as a List
Working
NOT WORKING
UPDATE
If I add it like this it works, but I'm trying to add a new one without knowing the list size.
val newGameRef = database.child("gamesList")
newGameRef.child(int.toString()).setValue(game)
database.child("date").setValue("23-08-2019 20:32")
The Firebase Realtime Database it always stores data as key-value pairs, with the keys being strings. In Java this translates to a Map<String,Object>. In some cases the Firebase clients are able to automatically convert the data to an array, which translates to List<Object> in your case. But in your second JSON screenshot, the client will not automatically convert the data to a List, so you'll have to do that yourself.
As Constantin commented, start by getting the Map<String, ...> from the database, and then get the list of values from that.
override fun onDataChange(p0: DataSnapshot) {
val map = p0.getValue(MapOfGamesJavaModel::class.java)!!
val database = map.values
val lastUpdate = database.date
}
The MapOfGamesJavaModel is a new class you'll have to create. Alternatively you can read Map<String, GamesJavaModel>, but you may have to do some casting with generic types in that case.
To learn more the way Firebase Realtime Database works with arrays, see Best Practices: Arrays in Firebase.
I am creating an app where users can upload photos and tag them, and then tags that they have uses are added to the list of that user's interests.
I am making a transition from Realtime database to cloud firestore and having a bit of an issue.
I want to store all these tags in an array inside a document for each user. Whenever a user uploads a photo, these tags should be added to this array.
I am using the update method as I don't want the list to be overwritten, but the data doesn't seem to be created at all. Could it be because for a new user the list doesn't actually exist?
I need the function to create the document and array if it is the first time the user adds any interests, or just update the list and add items if the array already exists.
Also, the tags are added to a complete list of all the tags across the app. For this one I've tried to use the set method but then the list just gets completely overwritten, even when I added SetOptions.merge()
val db = FirebaseFirestore.getInstance()
val userInterestsDoc = db.collection("interests").document(currentUser.uid)
val allTagsListDoc = db.collection("all_tags").document("all_tags")
for (tag in imageTagsList) {
userInterestsDoc.update("interests_list", FieldValue.arrayUnion(tag))
.addOnSuccessListener {
allTagsListDoc.set(
mapOf(
"all_tags_list" to arrayListOf(tag)
), SetOptions.merge()
)
}
This question already has answers here:
How to add new data in firebase android
(4 answers)
Closed 3 years ago.
In my application, I am able to take a screenshot from my cameras. Then I upload images to Firebase storage and get a download link. Now, I want to add this link to my database. I am able to do that by the following code:
fun storeImageUrlToFBDatabase(userId: String, cameraName: String, imageUrl: String) {
val map = mapOf(cameraName to imageUrl)
val ref = getFBDatabaseReference().getReference("users/$userId/images")
ref.setValue(map)
.addOnSuccessListener {
Logger.d("$FB_DATABASE_TAG, Write was successful, $it")
}
.addOnFailureListener {
Logger.e("$FB_DATABASE_TAG, Write failed: $it")
}
}
This is what Firebase shows:
However, the problem is the current item under images will be replaced by a new item I am pushing in. My expectation is something like this:
camera-streaming
users
userX
auth
token: "xxx"
userId: "xxxx"
images
image1: "url1"
image2: "url2"
image3: "url3"
image4: "url4"
But, what I get after each push/insert under images is having only one item/record. What is the problem?
You need to use key value to store the new links. This can be done in two ways:
Keep track of the current image sequence in the DB and then push the next value like:
val ref = getFBDatabaseReference().getReference("users/$userId/images");
//you need to find next xth image somehow
ref.child('imagex').setValue("map");
Just push the link to thee random key generated by DB:
val ref = getFBDatabaseReference().getReference("users/$userId/images");
val newRef = ref.push();
newRef.setValue("map");