Firestore returning less documents - android

So in my android app I'm fetching all the documents from a collection by the following code :
log("Player Listener Started")
FirebaseFirestore.getInstance().collection("players")
.limit(4)
.addSnapshotListener { querySnapshot, firebaseFirestoreException ->
log("Player Listener firestore exception message ${firebaseFirestoreException?.localizedMessage}")
if (firebaseFirestoreException == null) {
querySnapshot?.documents!!.forEach {
val serverPlayer = it.toObject(Player::class.java)!!
snapshotPlayers.add(serverPlayer)
}
log("Player numbers : ${snapshotPlayers.size}")
I've 4 documents in "players" collection in the database :
But it always return just 1 document i.e. "Sheetal". Please check the log from the above code :
This exact code was working fine an hour ago and I was getting all 4 users.
I cleared database from the console and re-created these document using my app this code is not returning 4 documents.
Player class :
class Player(
var name: String = "",
var gameId: String = "",
var currentCard: Card = Card(),
var cardList: ArrayList<Card> = ArrayList(),
var made: String = "0",
var expected: String = "0",
var message: String = "",
var order: Int = 0,
var turn: Int? = null
)
Player document contents in the database
I tried these things but still getting same result :
Clear my app cache manually
Cleared Firestore persistence data using FireDB.db.clearPersistence()
Its my first project in firestore so I don't know what am I doing wrong. Please help me.
UPDATED LOGCAT:

Related

How to map aggregated data from Firestore document back to a Kotlin List

Would like to reduce the number of reads in my app with Firestore. So I created a document in my collection with the following structure to hold values for 10 "records", that I will get with a single read - since the size of this document is pretty decent, no worries about the 1MB limit size for a single document. I am updating the content of this document with cloud functions.
name of collection: helperz
name of document: top10
field name in top10: tresholdCounter - this I need to check if a single map should be added to top10 or not
field name in top10: top10 . . array of maps
helperz/top10/tresholdCounter
helperz/top10/top10/0/author
helperz/top10/top10/0/name
helperz/top10/top10/0/url
helperz/top10/top10/1/author
helperz/top10/top10/1/name
helperz/top10/top10/1/url
helperz/top10/top10/2/author
helperz/top10/top10/2/name
helperz/top10/top10/2/url
helperz/top10/top10/3/author
helperz/top10/top10/3/name
helperz/top10/top10/3/url
helperz/top10/top10/4/author
helperz/top10/top10/4/name
helperz/top10/top10/4/url
..
helperz/top10/top10/10/author
helperz/top10/top10/10/name
helperz/top10/top10/10/url
I have a data class . . like this:
data class MyClass(
var name: String? = null,
var url: String? = null,
var author: String? = null,
var counter: Int = 0,
var free: Boolean? = false,
var global: Boolean?=true,
var poses: ArrayList<MyPoze>? = null,
var docId: string? = null,
var category: ArrayList<String>? = null,
#get:PropertyName(CREATED)
#set:PropertyName(CREATED)
#ServerTimestamp var created: Timestamp? = null
)
There are some other fields as well, but for the purpose of this problem, that should be ok.
I have a code for retrieving data from Firestore (in my viewModel):
private fun getHelperzTop10() = viewModelScope.launch {
Log.d("MP23", "getHelperzTop10")
val docRef = db.collection("helperz").document("top10")
docRef.addSnapshotListener { snapshot, e ->
if (e != null) {
Log.w("MP23", "Listen failed.", e)
return#addSnapshotListener
}
if (snapshot != null && snapshot.exists()) {
val docSize = firestoreDocument.getSize(snapshot);
Log.d("MP23","docSize in Bytes: $docSize, in KB: ${docSize * 0.001}, in MB: ${docSize * 0.000001}"
)
val top10 = snapshot.data
Log.d("MP23", top10!!::class.simpleName.toString() )
if ("top10" in keys) {
val top10arr = top10["top10"] as ArrayList<MyClass>
Log.d("MP23", "we have top10 in top10")
Log.d("MP23", top10arr!!::class.simpleName.toString())
Log.d("MP23", top10arr.toString())
//// 👇 PROBLEM HERE ///
// here I need somehow to cast this array of maps as MyClass, but I am getting error:
// java.util.ArrayList cannot be cast to java.lang.MyClass
// or
// java.util.ArrayList cannot be cast to java.lang.Object[] - with some other versions
}
} else {
Log.d("MP23", "Current data: null")
}
}
}
If someone can suggest how can I cast result to MyClass, that would be great. In normal situation (where I have documents that I query against) nicely as single docs, I can easily do:
val singleRec = singleRec.toObject(MyClass::class.java)
If you want to get the top10 array as a List<MyClass>, the simplest solution that I can think of would be to create another class:
data class Document(
var top10: MutableList<MyClass>? = null
)
And read the content of the document like this:
docRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
snapshot?.let {
val document = snapshot.toObject(Document::class.java)
document?.let {
val top10 = document.top10
top10?.let {
for (myClass in top10) {
val name = myClass.name
Log.d("TAG", "$name")
}
}
}
}
} else {
it.exception?.message?.let { message ->
Log.d("TAG", message) //Never ignore potential errors!
}
}
}
I will also recommend you read the following resource for a better understanding:
How to map an array of objects from Cloud Firestore to a List of objects?

FireStore Documents only showing sometimes

Fetching data from my FireStore DB is unreliable and it worsens after adding a new feature that uses the first date fetch to do some more data fetchs
I've my user songs (which are document ids to match the data)
To
//To get user data
suspend fun getAllUserPlaylists():List<Playlists>
= try{ FS_USER.get().await().toObjects(Playlists::class.java) }
catch (e:Exception){ emptyList() /*getAllUserPlaylists()*/ }
//Function to call above funcion
val allUserPlaylist = GlobalScope.launch { vm.allUserPlaylists. postValue(MusicDB(). getAllUserPlaylists()) }
runBlocking {
//wait for data fetch to finish
allUserPlaylist.join()
Log.i("WORKS","${vm.allUserPlaylists.value}")
//Match ids with song data
vm.allUserPlaylists.value?.forEach {
val q = arrayListOf<Song>()
it.songsIDs.forEach { it2 ->
val t = FS_ALL_SONGS.document(it2).get().await().toObject(Song::class.java)
if (t != null) {
q.add(t)
}
}
//Insert
val vmT = vm.allUserPlaylists.value!!
vmT[vmT.indexOf(it)].songs = q
vm.allUserPlaylists.postValue(vmT)
}
}
data class Song(val mediaID: String = "", val title: String = "",
val artist: String = "", val songURL: String = "",
val imgURL: String = "", val album: String = "")
data class Playlists(val name:String= "", val mainArtists: String = "",
var songs:ArrayList<Song> = arrayListOf(),
val songsIDs:ArrayList<String> = arrayListOf(),
val imgURL:String = "",var pinned:Boolean = false)
What i dont get why is it so unreliable.In theory it should work but only does (10% of the time) after clearing all app data and cache.I simpliy add documents to a list with using their doc ids and display it using a recycler view that updates on value change.
So any sort of help is appreicated
Edited : My code doesn't provide any visible errors (to me) however even though getAllUsersPlaylists function returns valid results(doc IDs) which I've confirmed by logging.
Code snippet to match doc IDs with song data doesn't give expected results(also checked by logging).It doesn't match the Doc Ids with data so doesn't return song data that I've referred using its doc IDs.
And this data is later shown to the user using a recycler view which auto updates ui
Song IDs refer to the doc IDs for song data

How do you properly model a JSON map in android

I'm trying to pass a map from Firestore into a data class but I'm getting null instead of the data
This is how my data is accessed:
firestoreDb = FirebaseFirestore.getInstance()
val postsRef = firestoreDb
.collection("posts")
.limit(20)
.orderBy("creation_time_ms", Query.Direction.DESCENDING)
.orderBy("date", Query.Direction.DESCENDING)
postsRef.addSnapshotListener { snapshot, exception ->
if (exception != null || snapshot == null) {
Log.e(TAG,"Exception when querying post", exception )
return#addSnapshotListener
}
val postList = snapshot.toObjects(HousePost::class.java)
for (post in postList) {
Log.i(TAG, "Posts $post")
}
}
My model for the data
data class HousePost (
#get:PropertyName("image_url") #set:PropertyName("image_url") var postImage: String = "",
var rent: String = "",
var description: String = "",
#get:PropertyName("creation_time_ms") #set:PropertyName("creation_time_ms") var creationTimeMs: Long = 0L,
var location: String = "",
#get:PropertyName("post_id") #set:PropertyName("post_id")var postId: String? = "",
var rooms: String = "",
var caption: String = "",
var date: String = "",
var owner: Owner? = null
)
My Owner model class
class Owner(
var uid: String = "",
var username: String = "",
var email: String = "",
#get:PropertyName("profile_image") #set:PropertyName("profile_image") var profileImage: String = "",
#get:PropertyName("user_type") #set:PropertyName("user_type")var usertype: String = "owner"
)
Here is my firestore data I know some fields are an empty string but that shouldn't output null.
This is the result from logcat
2022-05-03 11:42:12.313 6581-6581/com.example.moveapplication I/MainActivity: Posts HousePost(postImage=https://firebasestorage.googleapis.com/v0/b/moveapplicationdb.appspot.com/o/Post%20Pictures%2Fian-dooley-_-JR5TxKNSo-unsplash.jpg?alt=media&token=6721ec57-7602-41ee-b7cd-b8b1838b27fc, rent=15000, description=Along Ngong road we have a studio room for you to rent. Located in a moder =n area with nice infrastrucure, creationTimeMs=1651561930185, location=Lenana, postId=, rooms=studio room, caption=studio room along Ngong road, date=03/05/2022, owner=null)
My index from firestore
Looking at your class definitions, all look fine. You're using the correct annotations. However, when you're using the following query:
val postsRef = firestoreDb
.collection("posts")
.limit(20)
You'll need to know that you have to create an index. It can be manually created inside the Firebase Console or if you are using Android Studio, you'll find a message in the logcat that sounds like this:
FAILED_PRECONDITION: The query requires an index. You can create it here: ...
Simply click on that link or copy and paste the URL into a web browser and your index will be created automatically for you.

What should I do to print only the last data entered in Text?

private fun getData(){
firestore.collection("Posts").addSnapshotListener { value, error ->
if (error!=null){
Toast.makeText(requireContext(),error.localizedMessage,Toast.LENGTH_SHORT).show()
}else{
if (value !=null){
if (!value.isEmpty){
val documents = value.documents
for (document in documents){
val pc = document.get("Panel Sayisi") as String
val ps = document.get("Panel Boyutu") as String
val ls = document.get("Arazi EÄŸimi") as String
val lsi = document.get("Arazi Boyutu") as String
val c = document.get("Åžehir") as String
val post = Post(pc,ps,ls,lsi,c)
postArrayList.add(post)
}
}
}
}
val db = FirebaseFirestore.getInstance()
db.collection("Posts").orderBy("Panel Sayisi",Query.Direction.DESCENDING).limit(1)
.get()
.addOnCompleteListener {
val result : StringBuffer = StringBuffer()
if (it.isSuccessful){
for (document in it.result){
result.append(document.data.getValue("Panel Sayisi"))
}
verimText.setText(result)
}
}
}
}
It shows all the data I have added to Cloud Firestore that has the keyword "Panel Sayisi" in verimText. I only want the last data entered to be displayed.
Here is the problem. The last file I added is added in the middle. That's why the value I call last or the first call doesn't change. So it always calls the same value. This middle value should be written at the end or at the beginning. So I can get this data by calling ASCENDING or DESCENDING method.
When you are using the following call to:
.orderBy("Panel Sayisi",Query.Direction.DESCENDING)
It means that are only ordering the documents according to the "Panel Sayisi" field, which doesn't actually solve the problem. The problem is that you don't know that the "c4Q5...q4vP" document is the last document that was added. To solve this issue, you have to add an additional field of type Firestore Timestamp, as explained in my answer from the following post:
How to add Firebase Timestamp when adding an object of a data class to the Firestore in Kotlin?
And then use the following query:
val db = FirebaseFirestore.getInstance()
val query = db.collection("Posts").orderBy("timestamp", Query.Direction.DESCENDING).limit(1)

Failed to read data from firebase firestore after Changing the device date (Android and emulator) for nearly 30 days

i'm developing a quiz app. it is working fine.
but when i change the device date like more than 30 days, it is unable to read data from firestore.
see my code
private fun getDataforDQuiz() {
val docRef = db.collection("MonthlyQuiz")
.document(getQuizNum.toString())
docRef.get()
.addOnSuccessListener { documentSnapshot ->
if (documentSnapshot != null) {
val x = documentSnapshot.toObject<QuizModelClass>()
if (x != null) {
if (x.img != "" && x.img.isNotEmpty()) {
activity?.let {
Glide.with(it)
.load(x.img)
.fitCenter()
.into(imageViewToShow)
}
} else {
imageViewToShow.visibility = View.GONE
}
correctAnswer = x.answer
radio_pirates.text = x.a
radio_ninjas.text = x.b
radio_donny.text = x.c
radio_monny.text = x.d
text_to_show.text = x.text
}
}
}.addOnFailureListener {
Toast.makeText(activity, "failed to load data", Toast.LENGTH_SHORT).show()
}
}
my QuizModelClass
class QuizModelClass {
var a: String = ""
var b: String = ""
var c: String = ""
var d: String = ""
var answer: String = ""
var img: String = ""
var text: String = ""
constructor(
A :String,
B:String,
C:String,
D:String,
Answer:String,
Img:String,
Text:String,
)
{
a=A
b=B
c=C
d=D
answer=Answer
img=Img
text=Text
}
constructor() {}
}
I have three functions for daily, weekly and monthly quizzes. First two are working fine.
my doubt is does firestore impose any limitations on reading data for changing the dates ?
i have also noticed i can't create a new account when i changed the date. and also can not login.
i'm getting the toast message "failed to load data"
my database
MonthlyQuiz (collection)
1(document)-> data
2(document)->data
my data base structure screenshot
getQuizNum.toString() is just a number to reference the document in quiz collection. I save the previous quiz number in shared pref and use it to get next month quiz data.

Categories

Resources